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

Subversion リポジトリの参照

Diff of /trunk/1.8.x/ccs-patch/security/ccsecurity/policy_io.c

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

revision 2894 by kumaneko, Tue Aug 11 08:15:11 2009 UTC revision 2916 by kumaneko, Mon Aug 17 12:23:47 2009 UTC
# Line 15  Line 15 
15  /* Lock for protecting ccs_profile->comment  */  /* Lock for protecting ccs_profile->comment  */
16  static DEFINE_SPINLOCK(ccs_profile_comment_lock);  static DEFINE_SPINLOCK(ccs_profile_comment_lock);
17    
18  static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +  /* String table for functionality that takes 2 modes. */
19                                     CCS_MAX_CAPABILITY_INDEX + 1];  static const char *ccs_mode_2[2] = {
20            "disabled", "enabled"
21    };
22    
23  /* String table for functionality that takes 4 modes. */  static const char *ccs_keyword_mode[4] = {
24  static const char *ccs_mode_4[4] = {          "MAC_MODE_DISABLED", "MAC_MODE_LEARNING",
25          "disabled", "learning", "permissive", "enforcing"          "MAC_MODE_PERMISSIVE", "MAC_MODE_ENFORCING"
26  };  };
27  /* String table for functionality that takes 2 modes. */  
28  static const char *ccs_mode_2[4] = {  static const char *ccs_keyword_capability_mode[4] = {
29          "disabled", "enabled", "enabled", "enabled"          "MAC_MODE_CAPABILITY_DISABLED", "MAC_MODE_CAPABILITY_LEARNING",
30            "MAC_MODE_CAPABILITY_PERMISSIVE", "MAC_MODE_CAPABILITY_ENFORCING"
31    };
32    
33    static const char *ccs_mac_keywords[CCS_MAX_MAC_INDEX] = {
34            [CCS_MAC_EXECUTE]    = "execute",
35            [CCS_MAC_OPEN]       = "open",
36            [CCS_MAC_CREATE]     = "create",
37            [CCS_MAC_UNLINK]     = "unlink",
38            [CCS_MAC_MKDIR]      = "mkdir",
39            [CCS_MAC_RMDIR]      = "rmdir",
40            [CCS_MAC_MKFIFO]     = "mkfifo",
41            [CCS_MAC_MKSOCK]     = "mksock",
42            [CCS_MAC_TRUNCATE]   = "truncate",
43            [CCS_MAC_SYMLINK]    = "symlink",
44            [CCS_MAC_REWRITE]    = "rewrite",
45            [CCS_MAC_MKBLOCK]    = "mkblock",
46            [CCS_MAC_MKCHAR]     = "mkchar",
47            [CCS_MAC_LINK]       = "link",
48            [CCS_MAC_RENAME]     = "rename",
49            [CCS_MAC_CHMOD]      = "chmod",
50            [CCS_MAC_CHOWN]      = "chown",
51            [CCS_MAC_CHGRP]      = "chgrp",
52            [CCS_MAC_IOCTL]      = "ioctl",
53            [CCS_MAC_CHROOT]     = "chroot",
54            [CCS_MAC_MOUNT]      = "mount",
55            [CCS_MAC_UMOUNT]     = "umount",
56            [CCS_MAC_PIVOT_ROOT] = "pivot_root",
57            [CCS_MAC_ENVIRON]    = "env",
58            [CCS_MAC_NETWORK]    = "network",
59            [CCS_MAC_SIGNAL]     = "signal"
60  };  };
61    
62  /* Table for profile. */  /* Table for profile. */
# Line 33  static struct { Line 65  static struct {
65          unsigned int current_value;          unsigned int current_value;
66          const unsigned int max_value;          const unsigned int max_value;
67  } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {  } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {
         [CCS_MAC_FOR_FILE]        = { "MAC_FOR_FILE",        0, 3 },  
68          [CCS_AUTOLEARN_EXEC_REALPATH] = { "AUTOLEARN_EXEC_REALPATH", 0, 1 },          [CCS_AUTOLEARN_EXEC_REALPATH] = { "AUTOLEARN_EXEC_REALPATH", 0, 1 },
69          [CCS_AUTOLEARN_EXEC_ARGV0] = { "AUTOLEARN_EXEC_ARGV0", 0, 1 },          [CCS_AUTOLEARN_EXEC_ARGV0] = { "AUTOLEARN_EXEC_ARGV0", 0, 1 },
         [CCS_MAC_FOR_IOCTL]       = { "MAC_FOR_IOCTL",       0, 3 },  
         [CCS_MAC_FOR_FILEATTR]    = { "MAC_FOR_FILEATTR",    0, 3 },  
         [CCS_MAC_FOR_ENV]         = { "MAC_FOR_ENV",         0, 3 },  
         [CCS_MAC_FOR_NETWORK]     = { "MAC_FOR_NETWORK",     0, 3 },  
         [CCS_MAC_FOR_SIGNAL]      = { "MAC_FOR_SIGNAL",      0, 3 },  
         [CCS_MAC_FOR_NAMESPACE]   = { "MAC_FOR_NAMESPACE",   0, 3 },  
70          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },
71          [CCS_MAX_ACCEPT_ENTRY]          [CCS_MAX_ACCEPT_ENTRY]
72          = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },          = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },
# Line 126  static struct ccs_profile *ccs_find_or_a Line 151  static struct ccs_profile *ccs_find_or_a
151                  ptr = entry;                  ptr = entry;
152                  for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)                  for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
153                          ptr->value[i] = ccs_control_array[i].current_value;                          ptr->value[i] = ccs_control_array[i].current_value;
                 /*  
                  * Needn't to initialize "ptr->capability_value"  
                  * because they are always 0.  
                  */  
154                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
155                  ccs_profile_ptr[profile] = ptr;                  ccs_profile_ptr[profile] = ptr;
156                  entry = NULL;                  entry = NULL;
# Line 151  static int ccs_write_profile(struct ccs_ Line 172  static int ccs_write_profile(struct ccs_
172          char *data = head->write_buf;          char *data = head->write_buf;
173          unsigned int i;          unsigned int i;
174          unsigned int value;          unsigned int value;
175            int mode;
176          char *cp;          char *cp;
177          struct ccs_profile *ccs_profile;          struct ccs_profile *ccs_profile;
178          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
# Line 178  static int ccs_write_profile(struct ccs_ Line 200  static int ccs_write_profile(struct ccs_
200                  spin_unlock(&ccs_profile_comment_lock);                  spin_unlock(&ccs_profile_comment_lock);
201                  /***** CRITICAL SECTION END *****/                  /***** CRITICAL SECTION END *****/
202                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
                 ccs_profile_entry_used[0] = true;  
203                  return 0;                  return 0;
204          }          }
205          if (ccs_str_starts(&data, CCS_KEYWORD_MAC_FOR_CAPABILITY)) {          for (mode = 0; mode < 4; mode++) {
206                  if (sscanf(cp + 1, "%u", &value) != 1) {                  if (strcmp(data, ccs_keyword_mode[mode]))
207                          for (i = 0; i < 4; i++) {                          continue;
208                                  if (strcmp(cp + 1, ccs_mode_4[i]))                  cp++;
209                    while (1) {
210                            char *cp2 = strchr(cp, ' ');
211                            if (cp2)
212                                    *cp2 = '\0';
213                            for (i = 0; i < CCS_MAX_MAC_INDEX; i++) {
214                                    if (strcmp(cp, ccs_mac_keywords[i]))
215                                          continue;                                          continue;
216                                  value = i;                                  ccs_profile->mac_mode[i] = mode;
                                 break;  
217                          }                          }
218                          if (i == 4)                          if (!cp2)
219                                  return -EINVAL;                                  break;
220                            cp = cp2 + 1;
221                  }                  }
222                  if (value > 3)                  return 0;
223                          value = 3;          }
224                  for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {          for (mode = 0; mode < 4; mode++) {
225                          if (strcmp(data, ccs_capability_control_keyword[i]))                  if (strcmp(data, ccs_keyword_capability_mode[mode]))
226                                  continue;                          continue;
227                          ccs_profile->capability_value[i] = value;                  cp++;
228                          ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]                  while (1) {
229                                  = true;                          char *cp2 = strchr(cp, ' ');
230                          return 0;                          if (cp2)
231                                    *cp2 = '\0';
232                            for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
233                                    if (strcmp(cp, ccs_capability_list[i]))
234                                            continue;
235                                    ccs_profile->mac_capability_mode[i] = mode;
236                            }
237                            if (!cp2)
238                                    break;
239                            cp = cp2 + 1;
240                  }                  }
241                  return -EINVAL;                  return 0;
242          }          }
243          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
244                  if (strcmp(data, ccs_control_array[i].keyword))                  if (strcmp(data, ccs_control_array[i].keyword))
245                          continue;                          continue;
246                  if (sscanf(cp + 1, "%u", &value) != 1) {                  if (sscanf(cp + 1, "%u", &value) != 1) {
247                          int j;                          int j;
248                          const char **modes;                          for (j = 0; j < 2; j++) {
249                          switch (i) {                                  if (strcmp(cp + 1, ccs_mode_2[j]))
                         case CCS_AUTOLEARN_EXEC_REALPATH:  
                         case CCS_AUTOLEARN_EXEC_ARGV0:  
                         case CCS_RESTRICT_AUTOBIND:  
                         case CCS_VERBOSE:  
                                 modes = ccs_mode_2;  
                                 break;  
                         default:  
                                 modes = ccs_mode_4;  
                                 break;  
                         }  
                         for (j = 0; j < 4; j++) {  
                                 if (strcmp(cp + 1, modes[j]))  
250                                          continue;                                          continue;
251                                  value = j;                                  value = j;
252                                  break;                                  break;
# Line 233  static int ccs_write_profile(struct ccs_ Line 257  static int ccs_write_profile(struct ccs_
257                          value = ccs_control_array[i].max_value;                          value = ccs_control_array[i].max_value;
258                  }                  }
259                  ccs_profile->value[i] = value;                  ccs_profile->value[i] = value;
                 ccs_profile_entry_used[i + 1] = true;  
260                  return 0;                  return 0;
261          }          }
262          return -EINVAL;          return -EINVAL;
263  }  }
264    
265    static bool ccs_print_mac_mode(struct ccs_io_buffer *head, u8 index)
266    {
267            const int pos = head->read_avail;
268            int i;
269            int mode;
270            const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
271            for (mode = 0; mode < 4; mode++) {
272                    if (!ccs_io_printf(head, "%u-%s={", index, ccs_keyword_mode[mode]))
273                            goto out;
274                    for (i = 0; i < CCS_MAX_MAC_INDEX; i++) {
275                            if (ccs_profile->mac_mode[i] != mode)
276                                    continue;
277                            if (!ccs_io_printf(head, " %s", ccs_mac_keywords[i]))
278                                    goto out;
279                    }
280                    if (!ccs_io_printf(head, " }\n"))
281                            goto out;
282            }
283            return true;
284     out:
285            head->read_avail = pos;
286            return false;
287    }
288    
289    static bool ccs_print_capability_mode(struct ccs_io_buffer *head, u8 index)
290    {
291            const int pos = head->read_avail;
292            int i;
293            int mode;
294            const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];
295            for (mode = 0; mode < 4; mode++) {
296                    if (!ccs_io_printf(head, "%u-%s={", index, ccs_keyword_capability_mode[mode]))
297                            goto out;
298                    for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {
299                            if (ccs_profile->mac_capability_mode[i] != mode)
300                                    continue;
301                            if (!ccs_io_printf(head, " %s", ccs_capability_list[i]))
302                                    goto out;
303                    }
304                    if (!ccs_io_printf(head, " }\n"))
305                            goto out;
306            }
307            return true;
308     out:
309            head->read_avail = pos;
310            return false;
311    }
312    
313  /**  /**
314   * ccs_read_profile - Read profile table.   * ccs_read_profile - Read profile table.
315   *   *
# Line 248  static int ccs_write_profile(struct ccs_ Line 319  static int ccs_write_profile(struct ccs_
319   */   */
320  static int ccs_read_profile(struct ccs_io_buffer *head)  static int ccs_read_profile(struct ccs_io_buffer *head)
321  {  {
322          static const int ccs_total          static const int ccs_total = CCS_MAX_CONTROL_INDEX + 2;
                 = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;  
323          int step;          int step;
324          if (head->read_eof)          if (head->read_eof)
325                  return 0;                  return 0;
# Line 261  static int ccs_read_profile(struct ccs_i Line 331  static int ccs_read_profile(struct ccs_i
331                  head->read_step = step;                  head->read_step = step;
332                  if (!ccs_profile)                  if (!ccs_profile)
333                          continue;                          continue;
                 if (!ccs_profile_entry_used[type])  
                         continue;  
334                  if (!type) { /* Print profile' comment tag. */                  if (!type) { /* Print profile' comment tag. */
335                          bool done;                          bool done;
336                          /***** CRITICAL SECTION START *****/                          /***** CRITICAL SECTION START *****/
# Line 275  static int ccs_read_profile(struct ccs_i Line 343  static int ccs_read_profile(struct ccs_i
343                          if (!done)                          if (!done)
344                                  break;                                  break;
345                          continue;                          continue;
346                  }                  } else if (type == 1) {
347                  type--;                          if (!ccs_print_mac_mode(head, index))
348                  if (type >= CCS_MAX_CONTROL_INDEX) {                                  break;
349                          const int i = type - CCS_MAX_CONTROL_INDEX;                          continue;
350                          const u8 value = ccs_profile->capability_value[i];                  } else if (type == 2) {
351                          if (!ccs_io_printf(head,                          if (!ccs_print_capability_mode(head, index))
                                            "%u-" CCS_KEYWORD_MAC_FOR_CAPABILITY  
                                            "%s=%s\n", index,  
                                            ccs_capability_control_keyword[i],  
                                            ccs_mode_4[value]))  
352                                  break;                                  break;
353                  } else {                          continue;
354                    }
355                    type -= 3;
356                    {
357                          const unsigned int value = ccs_profile->value[type];                          const unsigned int value = ccs_profile->value[type];
                         const char **modes = NULL;  
358                          const char *keyword = ccs_control_array[type].keyword;                          const char *keyword = ccs_control_array[type].keyword;
359                          switch (ccs_control_array[type].max_value) {                          if (ccs_control_array[type].max_value == 1) {
                         case 3:  
                                 modes = ccs_mode_4;  
                                 break;  
                         case 1:  
                                 modes = ccs_mode_2;  
                                 break;  
                         }  
                         if (modes) {  
360                                  if (!ccs_io_printf(head, "%u-%s=%s\n", index,                                  if (!ccs_io_printf(head, "%u-%s=%s\n", index,
361                                                     keyword, modes[value]))                                                     keyword, ccs_mode_2[value]))
362                                          break;                                          break;
363                          } else {                          } else {
364                                  if (!ccs_io_printf(head, "%u-%s=%u\n", index,                                  if (!ccs_io_printf(head, "%u-%s=%u\n", index,
# Line 329  static int ccs_update_manager_entry(cons Line 387  static int ccs_update_manager_entry(cons
387  {  {
388          struct ccs_policy_manager_entry *entry = NULL;          struct ccs_policy_manager_entry *entry = NULL;
389          struct ccs_policy_manager_entry *ptr;          struct ccs_policy_manager_entry *ptr;
390          const struct ccs_path_info *saved_manager;          struct ccs_policy_manager_entry e = { };
391          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
         bool is_domain = false;  
392          if (ccs_is_domain_def(manager)) {          if (ccs_is_domain_def(manager)) {
393                  if (!ccs_is_correct_domain(manager))                  if (!ccs_is_correct_domain(manager))
394                          return -EINVAL;                          return -EINVAL;
395                  is_domain = true;                  e.is_domain = true;
396          } else {          } else {
397                  if (!ccs_is_correct_path(manager, 1, -1, -1))                  if (!ccs_is_correct_path(manager, 1, -1, -1))
398                          return -EINVAL;                          return -EINVAL;
399          }          }
400          saved_manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
401          if (!saved_manager)          if (!e.manager)
402                  return -ENOMEM;                  return -ENOMEM;
403          if (!is_delete)          if (!is_delete)
404                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);                  entry = kmalloc(sizeof(e), GFP_KERNEL);
405          mutex_lock(&ccs_policy_lock);          mutex_lock(&ccs_policy_lock);
406          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
407                  if (ptr->manager != saved_manager)                  if (ptr->manager != e.manager)
408                          continue;                          continue;
409                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
410                  error = 0;                  error = 0;
411                  break;                  break;
412          }          }
413          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {          if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {
                 entry->manager = saved_manager;  
                 saved_manager = NULL;  
                 entry->is_domain = is_domain;  
414                  list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);                  list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
415                  entry = NULL;                  entry = NULL;
416                  error = 0;                  error = 0;
417          }          }
418          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
419          ccs_put_name(saved_manager);          ccs_put_name(e.manager);
420          kfree(entry);          kfree(entry);
421          return error;          return error;
422  }  }
# Line 553  static bool ccs_is_select_one(struct ccs Line 607  static bool ccs_is_select_one(struct ccs
607          return true;          return true;
608  }  }
609    
610    static int ccs_write_domain_policy2(char *data, struct ccs_domain_info *domain,
611                                        struct ccs_condition *cond,
612                                        const bool is_delete)
613    {
614            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))
615                    return ccs_write_capability_policy(data, domain, cond,
616                                                       is_delete);
617            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))
618                    return ccs_write_network_policy(data, domain, cond, is_delete);
619            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))
620                    return ccs_write_signal_policy(data, domain, cond, is_delete);
621            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
622                    return ccs_write_env_policy(data, domain, cond, is_delete);
623            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))
624                    return ccs_write_mount_policy(data, domain, cond, is_delete);
625            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT))
626                    return ccs_write_umount_policy(data, domain, cond, is_delete);
627            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT))
628                    return ccs_write_chroot_policy(data, domain, cond, is_delete);
629            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT))
630                    return ccs_write_pivot_root_policy(data, domain, cond,
631                                                       is_delete);
632            return ccs_write_file_policy(data, domain, cond, is_delete);
633    }
634    
635  /**  /**
636   * ccs_write_domain_policy - Write domain policy.   * ccs_write_domain_policy - Write domain policy.
637   *   *
# Line 613  static int ccs_write_domain_policy(struc Line 692  static int ccs_write_domain_policy(struc
692                  if (!cond)                  if (!cond)
693                          return -EINVAL;                          return -EINVAL;
694          }          }
695          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))          error = ccs_write_domain_policy2(data, domain, cond, is_delete);
                 error = ccs_write_capability_policy(data, domain, cond,  
                                                     is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))  
                 error = ccs_write_network_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))  
                 error = ccs_write_signal_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))  
                 error = ccs_write_env_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))  
                 error = ccs_write_mount_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT))  
                 error = ccs_write_umount_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT))  
                 error = ccs_write_chroot_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT))  
                 error = ccs_write_pivot_root_policy(data, domain, cond,  
                                                     is_delete);  
         else  
                 error = ccs_write_file_policy(data, domain, cond, is_delete);  
696          if (cond)          if (cond)
697                  ccs_put_condition(cond);                  ccs_put_condition(cond);
698          return error;          return error;
# Line 702  static bool ccs_print_number_union_commo Line 762  static bool ccs_print_number_union_commo
762          }          }
763  }  }
764    
765  static bool ccs_print_number_union(struct ccs_io_buffer *head,  bool ccs_print_number_union(struct ccs_io_buffer *head,
766                                     const struct ccs_number_union *ptr)                              const struct ccs_number_union *ptr)
767  {  {
768          return ccs_print_number_union_common(head, ptr, true);          return ccs_print_number_union_common(head, ptr, true);
769  }  }
# Line 826  static bool ccs_print_condition(struct c Line 886  static bool ccs_print_condition(struct c
886  }  }
887    
888  /**  /**
889   * ccs_print_single_path_acl - Print a single path ACL entry.   * ccs_print_path_acl - Print a single path ACL entry.
890   *   *
891   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
892   * @ptr:  Pointer to "struct ccs_single_path_acl_record".   * @ptr:  Pointer to "struct ccs_path_acl".
893   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
894   *   *
895   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
896   */   */
897  static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_acl(struct ccs_io_buffer *head,
898                                        struct ccs_single_path_acl_record *ptr,                                        struct ccs_path_acl *ptr,
899                                        const struct ccs_condition *cond)                                        const struct ccs_condition *cond)
900  {  {
901          int pos;          int pos;
902          u8 bit;          u8 bit;
903          const u16 perm = ptr->perm;          const u16 perm = ptr->perm;
904          for (bit = head->read_bit; bit < CCS_MAX_SINGLE_PATH_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_OPERATION; bit++) {
                 const char *msg;  
905                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
906                          continue;                          continue;
907                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE_ACL)                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE)
908                          continue;                          continue;
909                  /* Print "read/write" instead of "read" and "write". */                  /* Print "read/write" instead of "read" and "write". */
910                  if ((bit == CCS_TYPE_READ_ACL || bit == CCS_TYPE_WRITE_ACL)                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
911                      && (perm & (1 << CCS_TYPE_READ_WRITE_ACL)))                      && (perm & (1 << CCS_TYPE_READ_WRITE)))
912                          continue;                          continue;
                 msg = ccs_sp2keyword(bit);  
913                  pos = head->read_avail;                  pos = head->read_avail;
914                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||
915                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
916                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
917                          goto out;                          head->read_bit = bit;
918                            head->read_avail = pos;
919                            return false;
920                    }
921          }          }
922          head->read_bit = 0;          head->read_bit = 0;
923          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
924  }  }
925    
926  /**  /**
927   * ccs_print_mkdev_acl - Print a mkdev ACL entry.   * ccs_print_path_number_number_acl - Print a path_number_number ACL entry.
928   *   *
929   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
930   * @ptr:  Pointer to "struct ccs_mkdev_acl_record".   * @ptr:  Pointer to "struct ccs_path_number_number_acl".
931   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
932   *   *
933   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
934   */   */
935  static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number_number_acl(struct ccs_io_buffer *head,
936                                  struct ccs_mkdev_acl_record *ptr,                                  struct ccs_path_number_number_acl *ptr,
937                                  const struct ccs_condition *cond)                                  const struct ccs_condition *cond)
938  {  {
939          int pos;          int pos;
940          u8 bit;          u8 bit;
941          const u16 perm = ptr->perm;          const u16 perm = ptr->perm;
942          for (bit = head->read_bit; bit < CCS_MAX_MKDEV_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_NUMBER_OPERATION;
943                  const char *msg;               bit++) {
944                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
945                          continue;                          continue;
                 msg = ccs_mkdev2keyword(bit);  
946                  pos = head->read_avail;                  pos = head->read_avail;
947                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
948                                       ccs_path_number_number2keyword(bit)) ||
949                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
950                      !ccs_print_number_union(head, &ptr->major) ||                      !ccs_print_number_union(head, &ptr->major) ||
951                      !ccs_print_number_union(head, &ptr->minor) ||                      !ccs_print_number_union(head, &ptr->minor) ||
952                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
953                          goto out;                          head->read_bit = bit;
954                            head->read_avail = pos;
955                            return false;
956                    }
957          }          }
958          head->read_bit = 0;          head->read_bit = 0;
959          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
960  }  }
961    
962  /**  /**
963   * ccs_print_double_path_acl - Print a double path ACL entry.   * ccs_print_path_path_acl - Print a double path ACL entry.
964   *   *
965   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
966   * @ptr:  Pointer to "struct ccs_double_path_acl_record".   * @ptr:  Pointer to "struct ccs_path_path_acl".
967   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
968   *   *
969   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
970   */   */
971  static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_path_acl(struct ccs_io_buffer *head,
972                                        struct ccs_double_path_acl_record *ptr,                                        struct ccs_path_path_acl *ptr,
973                                        const struct ccs_condition *cond)                                        const struct ccs_condition *cond)
974  {  {
975          int pos;          int pos;
976          u8 bit;          u8 bit;
977          const u8 perm = ptr->perm;          const u8 perm = ptr->perm;
978          for (bit = head->read_bit; bit < CCS_MAX_DOUBLE_PATH_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_PATH_OPERATION; bit++) {
                 const char *msg;  
979                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
980                          continue;                          continue;
                 msg = ccs_dp2keyword(bit);  
981                  pos = head->read_avail;                  pos = head->read_avail;
982                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
983                                       ccs_path_path2keyword(bit)) ||
984                      !ccs_print_name_union(head, &ptr->name1) ||                      !ccs_print_name_union(head, &ptr->name1) ||
985                      !ccs_print_name_union(head, &ptr->name2) ||                      !ccs_print_name_union(head, &ptr->name2) ||
986                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
987                          goto out;                          head->read_bit = bit;
988                            head->read_avail = pos;
989                            return false;
990                    }
991          }          }
992          head->read_bit = 0;          head->read_bit = 0;
993          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
994  }  }
995    
996  /**  /**
997   * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.   * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.
998   *   *
999   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1000   * @ptr:  Pointer to "struct ccs_path_number_acl_record".   * @ptr:  Pointer to "struct ccs_path_number_acl".
1001   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1002   *   *
1003   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1004   */   */
1005  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
1006                                        struct ccs_path_number_acl_record *ptr,                                        struct ccs_path_number_acl *ptr,
1007                                        const struct ccs_condition *cond)                                        const struct ccs_condition *cond)
1008  {  {
1009          int pos;          int pos;
1010          u8 bit;          u8 bit;
1011          const u8 perm = ptr->perm;          const u8 perm = ptr->perm;
1012          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION;
1013                  const char *msg;               bit++) {
1014                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1015                          continue;                          continue;
                 msg = ccs_path_number2keyword(bit);  
1016                  pos = head->read_avail;                  pos = head->read_avail;
1017                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1018                                       ccs_path_number2keyword(bit)) ||
1019                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1020                      !ccs_print_number_union(head, &ptr->number) ||                      !ccs_print_number_union(head, &ptr->number) ||
1021                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
1022                          goto out;                          head->read_bit = bit;
1023                            head->read_avail = pos;
1024                            return false;
1025                    }
1026          }          }
1027          head->read_bit = 0;          head->read_bit = 0;
1028          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
1029  }  }
1030    
1031  /**  /**
1032   * ccs_print_env_acl - Print an evironment variable name's ACL entry.   * ccs_print_env_acl - Print an evironment variable name's ACL entry.
1033   *   *
1034   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1035   * @ptr:  Pointer to "struct ccs_env_acl_record".   * @ptr:  Pointer to "struct ccs_env_acl".
1036   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1037   *   *
1038   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1039   */   */
1040  static bool ccs_print_env_acl(struct ccs_io_buffer *head,  static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1041                                struct ccs_env_acl_record *ptr,                                struct ccs_env_acl *ptr,
1042                                const struct ccs_condition *cond)                                const struct ccs_condition *cond)
1043  {  {
1044          int pos = head->read_avail;          const int pos = head->read_avail;
1045          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name))          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) ||
1046                  goto out;              !ccs_print_condition(head, cond)) {
1047          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1048                  goto out;                  return false;
1049            }
1050          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1051  }  }
1052    
1053  /**  /**
1054   * ccs_print_capability_acl - Print a capability ACL entry.   * ccs_print_capability_acl - Print a capability ACL entry.
1055   *   *
1056   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1057   * @ptr:  Pointer to "struct ccs_capability_acl_record".   * @ptr:  Pointer to "struct ccs_capability_acl".
1058   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1059   *   *
1060   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1061   */   */
1062  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1063                                       struct ccs_capability_acl_record *ptr,                                       struct ccs_capability_acl *ptr,
1064                                       const struct ccs_condition *cond)                                       const struct ccs_condition *cond)
1065  {  {
1066          int pos = head->read_avail;          const int pos = head->read_avail;
1067          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1068                             ccs_cap2keyword(ptr->operation)))                             ccs_cap2keyword(ptr->operation)) ||
1069                  goto out;              !ccs_print_condition(head, cond)) {
1070          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1071                  goto out;                  return false;
1072            }
1073          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1074  }  }
1075    
1076  /**  /**
1077   * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.   * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1078   *   *
1079   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1080   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1081   *   *
1082   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1083   */   */
1084  static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,  static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1085                                   struct ccs_ip_network_acl_record *ptr)                                   struct ccs_ip_network_acl *ptr)
1086  {  {
1087          const u32 min_address = ptr->address.ipv4.min;          const u32 min_address = ptr->address.ipv4.min;
1088          const u32 max_address = ptr->address.ipv4.max;          const u32 max_address = ptr->address.ipv4.max;
# Line 1049  static bool ccs_print_ipv4_entry(struct Line 1098  static bool ccs_print_ipv4_entry(struct
1098   * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.   * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1099   *   *
1100   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1101   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1102   *   *
1103   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1104   */   */
1105  static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,  static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1106                                   struct ccs_ip_network_acl_record *ptr)                                   struct ccs_ip_network_acl *ptr)
1107  {  {
1108          char buf[64];          char buf[64];
1109          const struct in6_addr *min_address = ptr->address.ipv6.min;          const struct in6_addr *min_address = ptr->address.ipv6.min;
# Line 1074  static bool ccs_print_ipv6_entry(struct Line 1123  static bool ccs_print_ipv6_entry(struct
1123   * ccs_print_network_acl - Print a network ACL entry.   * ccs_print_network_acl - Print a network ACL entry.
1124   *   *
1125   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1126   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1127   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1128   *   *
1129   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1130   */   */
1131  static bool ccs_print_network_acl(struct ccs_io_buffer *head,  static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1132                                    struct ccs_ip_network_acl_record *ptr,                                    struct ccs_ip_network_acl *ptr,
1133                                    const struct ccs_condition *cond)                                    const struct ccs_condition *cond)
1134  {  {
1135          int pos = head->read_avail;          int pos;
1136          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",          u8 bit;
1137                             ccs_net2keyword(ptr->operation_type)))          const u16 perm = ptr->perm;
1138                  goto out;          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1139          switch (ptr->record_type) {                  if (!(perm & (1 << bit)))
1140          case CCS_IP_RECORD_TYPE_ADDRESS_GROUP:                          continue;
1141                  if (!ccs_io_printf(head, "@%s",                  pos = head->read_avail;
1142                                     ptr->address.group->group_name->name))                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",
1143                          goto out;                                     ccs_net2keyword(bit)))
                 break;  
         case CCS_IP_RECORD_TYPE_IPv4:  
                 if (!ccs_print_ipv4_entry(head, ptr))  
1144                          goto out;                          goto out;
1145                  break;                  switch (ptr->address_type) {
1146          case CCS_IP_RECORD_TYPE_IPv6:                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1147                  if (!ccs_print_ipv6_entry(head, ptr))                          if (!ccs_io_printf(head, "@%s", ptr->address.group->
1148                                               group_name->name))
1149                                    goto out;
1150                            break;
1151                    case CCS_IP_ADDRESS_TYPE_IPv4:
1152                            if (!ccs_print_ipv4_entry(head, ptr))
1153                                    goto out;
1154                            break;
1155                    case CCS_IP_ADDRESS_TYPE_IPv6:
1156                            if (!ccs_print_ipv6_entry(head, ptr))
1157                                    goto out;
1158                            break;
1159                    }
1160                    if (!ccs_print_number_union(head, &ptr->port) ||
1161                        !ccs_print_condition(head, cond))
1162                          goto out;                          goto out;
                 break;  
1163          }          }
1164          if (!ccs_print_number_union(head, &ptr->port) ||          head->read_bit = 0;
             !ccs_print_condition(head, cond))  
                 goto out;  
1165          return true;          return true;
1166   out:   out:
1167            head->read_bit = bit;
1168          head->read_avail = pos;          head->read_avail = pos;
1169          return false;          return false;
1170  }  }
# Line 1115  static bool ccs_print_network_acl(struct Line 1173  static bool ccs_print_network_acl(struct
1173   * ccs_print_signal_acl - Print a signal ACL entry.   * ccs_print_signal_acl - Print a signal ACL entry.
1174   *   *
1175   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1176   * @ptr:  Pointer to "struct signale_acl_record".   * @ptr:  Pointer to "struct signale_acl".
1177   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1178   *   *
1179   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1180   */   */
1181  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1182                                   struct ccs_signal_acl_record *ptr,                                   struct ccs_signal_acl *ptr,
1183                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1184  {  {
1185          int pos = head->read_avail;          const int pos = head->read_avail;
1186          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1187                             ptr->sig, ptr->domainname->name))                             ptr->sig, ptr->domainname->name) ||
1188                  goto out;              !ccs_print_condition(head, cond)) {
1189          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1190                  goto out;                  return false;
1191            }
1192          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1193  }  }
1194    
1195  /**  /**
# Line 1157  static bool ccs_print_execute_handler_re Line 1213  static bool ccs_print_execute_handler_re
1213   * ccs_print_mount_acl - Print a mount ACL entry.   * ccs_print_mount_acl - Print a mount ACL entry.
1214   *   *
1215   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1216   * @ptr:  Pointer to "struct ccs_mount_acl_record".   * @ptr:  Pointer to "struct ccs_mount_acl".
1217   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1218   *   *
1219   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1220   */   */
1221  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1222                                  struct ccs_mount_acl_record *ptr,                                  struct ccs_mount_acl *ptr,
1223                                  const struct ccs_condition *cond)                                  const struct ccs_condition *cond)
1224  {  {
1225          int pos = head->read_avail;          const int pos = head->read_avail;
1226          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
1227                             ptr->dev_name->name, ptr->dir_name->name,              !ccs_print_name_union(head, &ptr->dev_name) ||
1228                             ptr->fs_type->name, ptr->flags))              !ccs_print_name_union(head, &ptr->dir_name) ||
1229                  goto out;              !ccs_print_name_union(head, &ptr->fs_type) ||
1230          if (!ccs_print_condition(head, cond))              !ccs_print_number_union(head, &ptr->flags) ||
1231                  goto out;              !ccs_print_condition(head, cond)) {
1232                    head->read_avail = pos;
1233                    return false;
1234            }
1235          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1236  }  }
1237    
1238  /**  /**
1239   * ccs_print_umount_acl - Print a mount ACL entry.   * ccs_print_umount_acl - Print a mount ACL entry.
1240   *   *
1241   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1242   * @ptr:  Pointer to "struct ccs_umount_acl_record".   * @ptr:  Pointer to "struct ccs_umount_acl".
1243   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1244   *   *
1245   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1246   */   */
1247  static bool ccs_print_umount_acl(struct ccs_io_buffer *head,  static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
1248                                   struct ccs_umount_acl_record *ptr,                                   struct ccs_umount_acl *ptr,
1249                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1250  {  {
1251          int pos = head->read_avail;          const int pos = head->read_avail;
1252          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT "%s\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT) ||
1253                             ptr->dir->name))              !ccs_print_name_union(head, &ptr->dir) ||
1254                  goto out;              !ccs_print_condition(head, cond)) {
1255          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1256                  goto out;                  return false;
1257            }
1258          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1259  }  }
1260    
1261  /**  /**
1262   * ccs_print_chroot_acl - Print a chroot ACL entry.   * ccs_print_chroot_acl - Print a chroot ACL entry.
1263   *   *
1264   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1265   * @ptr:  Pointer to "struct ccs_chroot_acl_record".   * @ptr:  Pointer to "struct ccs_chroot_acl".
1266   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1267   *   *
1268   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1269   */   */
1270  static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,  static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
1271                                   struct ccs_chroot_acl_record *ptr,                                   struct ccs_chroot_acl *ptr,
1272                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1273  {  {
1274          int pos = head->read_avail;          const int pos = head->read_avail;
1275          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT "%s\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT) ||
1276                             ptr->dir->name))              !ccs_print_name_union(head, &ptr->dir) ||
1277                  goto out;              !ccs_print_condition(head, cond)) {
1278          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1279                  goto out;                  return false;
1280            }
1281          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1282  }  }
1283    
1284  /**  /**
1285   * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.   * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
1286   *   *
1287   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1288   * @ptr:  Pointer to "struct ccs_pivot_root_acl_record".   * @ptr:  Pointer to "struct ccs_pivot_root_acl".
1289   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1290   *   *
1291   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1292   */   */
1293  static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,  static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
1294                                       struct ccs_pivot_root_acl_record *ptr,                                       struct ccs_pivot_root_acl *ptr,
1295                                       const struct ccs_condition *cond)                                       const struct ccs_condition *cond)
1296  {  {
1297          int pos = head->read_avail;          const int pos = head->read_avail;
1298          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT) ||
1299                             ptr->new_root->name, ptr->old_root->name))              !ccs_print_name_union(head, &ptr->new_root) ||
1300                  goto out;              !ccs_print_name_union(head, &ptr->old_root) ||
1301          if (!ccs_print_condition(head, cond))              !ccs_print_condition(head, cond)) {
1302                  goto out;                  head->read_avail = pos;
1303                    return false;
1304            }
1305          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1306  }  }
1307    
1308  /**  /**
# Line 1266  static bool ccs_print_entry(struct ccs_i Line 1317  static bool ccs_print_entry(struct ccs_i
1317                              struct ccs_acl_info *ptr)                              struct ccs_acl_info *ptr)
1318  {  {
1319          const struct ccs_condition *cond = ptr->cond;          const struct ccs_condition *cond = ptr->cond;
1320          const u8 acl_type = ccs_acl_type2(ptr);          const u8 acl_type = ptr->type;
1321          if (acl_type & CCS_ACL_DELETED)          if (ptr->is_deleted)
1322                  return true;                  return true;
1323          if (acl_type == CCS_TYPE_SINGLE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH_ACL) {
1324                  struct ccs_single_path_acl_record *acl                  struct ccs_path_acl *acl
1325                          = container_of(ptr, struct ccs_single_path_acl_record,                          = container_of(ptr, struct ccs_path_acl,
1326                                         head);                                         head);
1327                  return ccs_print_single_path_acl(head, acl, cond);                  return ccs_print_path_acl(head, acl, cond);
1328          }          }
1329          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1330                  struct ccs_execute_handler_record *acl                  struct ccs_execute_handler_record *acl
# Line 1291  static bool ccs_print_entry(struct ccs_i Line 1342  static bool ccs_print_entry(struct ccs_i
1342          }          }
1343          if (head->read_execute_only)          if (head->read_execute_only)
1344                  return true;                  return true;
1345          if (acl_type == CCS_TYPE_MKDEV_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER_NUMBER_ACL) {
1346                  struct ccs_mkdev_acl_record *acl                  struct ccs_path_number_number_acl *acl
1347                          = container_of(ptr, struct ccs_mkdev_acl_record, head);                          = container_of(ptr, struct ccs_path_number_number_acl, head);
1348                  return ccs_print_mkdev_acl(head, acl, cond);                  return ccs_print_path_number_number_acl(head, acl, cond);
1349          }          }
1350          if (acl_type == CCS_TYPE_DOUBLE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH_PATH_ACL) {
1351                  struct ccs_double_path_acl_record *acl                  struct ccs_path_path_acl *acl
1352                          = container_of(ptr, struct ccs_double_path_acl_record,                          = container_of(ptr, struct ccs_path_path_acl,
1353                                         head);                                         head);
1354                  return ccs_print_double_path_acl(head, acl, cond);                  return ccs_print_path_path_acl(head, acl, cond);
1355          }          }
1356          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1357                  struct ccs_path_number_acl_record *acl                  struct ccs_path_number_acl *acl
1358                          = container_of(ptr, struct ccs_path_number_acl_record,                          = container_of(ptr, struct ccs_path_number_acl,
1359                                         head);                                         head);
1360                  return ccs_print_path_number_acl(head, acl, cond);                  return ccs_print_path_number_acl(head, acl, cond);
1361          }          }
1362          if (acl_type == CCS_TYPE_ENV_ACL) {          if (acl_type == CCS_TYPE_ENV_ACL) {
1363                  struct ccs_env_acl_record *acl                  struct ccs_env_acl *acl
1364                          = container_of(ptr, struct ccs_env_acl_record, head);                          = container_of(ptr, struct ccs_env_acl, head);
1365                  return ccs_print_env_acl(head, acl, cond);                  return ccs_print_env_acl(head, acl, cond);
1366          }          }
1367          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1368                  struct ccs_capability_acl_record *acl                  struct ccs_capability_acl *acl
1369                          = container_of(ptr, struct ccs_capability_acl_record,                          = container_of(ptr, struct ccs_capability_acl,
1370                                         head);                                         head);
1371                  return ccs_print_capability_acl(head, acl, cond);                  return ccs_print_capability_acl(head, acl, cond);
1372          }          }
1373          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1374                  struct ccs_ip_network_acl_record *acl                  struct ccs_ip_network_acl *acl
1375                          = container_of(ptr, struct ccs_ip_network_acl_record,                          = container_of(ptr, struct ccs_ip_network_acl,
1376                                         head);                                         head);
1377                  return ccs_print_network_acl(head, acl, cond);                  return ccs_print_network_acl(head, acl, cond);
1378          }          }
1379          if (acl_type == CCS_TYPE_SIGNAL_ACL) {          if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1380                  struct ccs_signal_acl_record *acl                  struct ccs_signal_acl *acl
1381                          = container_of(ptr, struct ccs_signal_acl_record, head);                          = container_of(ptr, struct ccs_signal_acl, head);
1382                  return ccs_print_signal_acl(head, acl, cond);                  return ccs_print_signal_acl(head, acl, cond);
1383          }          }
1384          if (acl_type == CCS_TYPE_MOUNT_ACL) {          if (acl_type == CCS_TYPE_MOUNT_ACL) {
1385                  struct ccs_mount_acl_record *acl                  struct ccs_mount_acl *acl
1386                          = container_of(ptr, struct ccs_mount_acl_record, head);                          = container_of(ptr, struct ccs_mount_acl, head);
1387                  return ccs_print_mount_acl(head, acl, cond);                  return ccs_print_mount_acl(head, acl, cond);
1388          }          }
1389          if (acl_type == CCS_TYPE_UMOUNT_ACL) {          if (acl_type == CCS_TYPE_UMOUNT_ACL) {
1390                  struct ccs_umount_acl_record *acl                  struct ccs_umount_acl *acl
1391                          = container_of(ptr, struct ccs_umount_acl_record, head);                          = container_of(ptr, struct ccs_umount_acl, head);
1392                  return ccs_print_umount_acl(head, acl, cond);                  return ccs_print_umount_acl(head, acl, cond);
1393          }          }
1394          if (acl_type == CCS_TYPE_CHROOT_ACL) {          if (acl_type == CCS_TYPE_CHROOT_ACL) {
1395                  struct ccs_chroot_acl_record *acl                  struct ccs_chroot_acl *acl
1396                          = container_of(ptr, struct ccs_chroot_acl_record, head);                          = container_of(ptr, struct ccs_chroot_acl, head);
1397                  return ccs_print_chroot_acl(head, acl, cond);                  return ccs_print_chroot_acl(head, acl, cond);
1398          }          }
1399          if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {          if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {
1400                  struct ccs_pivot_root_acl_record *acl                  struct ccs_pivot_root_acl *acl
1401                          = container_of(ptr, struct ccs_pivot_root_acl_record,                          = container_of(ptr, struct ccs_pivot_root_acl,
1402                                         head);                                         head);
1403                  return ccs_print_pivot_root_acl(head, acl, cond);                  return ccs_print_pivot_root_acl(head, acl, cond);
1404          }          }
         /* Workaround for gcc 3.2.2's inline bug. */  
         if (acl_type & CCS_ACL_DELETED)  
                 return true;  
1405          BUG(); /* This must not happen. */          BUG(); /* This must not happen. */
1406          return false;          return false;
1407  }  }
# Line 1690  static int ccs_read_exception_policy(str Line 1738  static int ccs_read_exception_policy(str
1738          return 0;          return 0;
1739  }  }
1740    
1741    /**
1742     * ccs_get_argv0 - Get argv[0].
1743     *
1744     * @ee: Pointer to "struct ccs_execve_entry".
1745     *
1746     * Returns true on success, false otherwise.
1747     */
1748    static bool ccs_get_argv0(struct ccs_execve_entry *ee)
1749    {
1750            struct linux_binprm *bprm = ee->bprm;
1751            char *arg_ptr = ee->tmp;
1752            int arg_len = 0;
1753            unsigned long pos = bprm->p;
1754            int offset = pos % PAGE_SIZE;
1755            bool done = false;
1756            if (!bprm->argc)
1757                    goto out;
1758            while (1) {
1759                    if (!ccs_dump_page(bprm, pos, &ee->dump))
1760                            goto out;
1761                    pos += PAGE_SIZE - offset;
1762                    /* Read. */
1763                    while (offset < PAGE_SIZE) {
1764                            const char *kaddr = ee->dump.data;
1765                            const unsigned char c = kaddr[offset++];
1766                            if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
1767                                    if (c == '\\') {
1768                                            arg_ptr[arg_len++] = '\\';
1769                                            arg_ptr[arg_len++] = '\\';
1770                                    } else if (c == '/') {
1771                                            arg_len = 0;
1772                                    } else if (c > ' ' && c < 127) {
1773                                            arg_ptr[arg_len++] = c;
1774                                    } else {
1775                                            arg_ptr[arg_len++] = '\\';
1776                                            arg_ptr[arg_len++] = (c >> 6) + '0';
1777                                            arg_ptr[arg_len++]
1778                                                    = ((c >> 3) & 7) + '0';
1779                                            arg_ptr[arg_len++] = (c & 7) + '0';
1780                                    }
1781                            } else {
1782                                    arg_ptr[arg_len] = '\0';
1783                                    done = true;
1784                                    break;
1785                            }
1786                    }
1787                    offset = 0;
1788                    if (done)
1789                            break;
1790            }
1791            return true;
1792     out:
1793            return false;
1794    }
1795    
1796    static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry
1797                                                           *ee)
1798    {
1799            struct ccs_condition *cond;
1800            char *buf;
1801            int len = 256;
1802            char *realpath = NULL;
1803            char *argv0 = NULL;
1804            if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) {
1805                    struct file *file = ee->bprm->file;
1806    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
1807                    struct path path = { file->f_vfsmnt, file->f_dentry };
1808                    realpath = ccs_realpath_from_path(&path);
1809    #else
1810                    realpath = ccs_realpath_from_path(&file->f_path);
1811    #endif
1812                    if (realpath)
1813                            len += strlen(realpath) + 17;
1814            }
1815            if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) {
1816                    if (ccs_get_argv0(ee)) {
1817                            argv0 = ee->tmp;
1818                            len += strlen(argv0) + 16;
1819                    }
1820            }
1821            buf = kmalloc(len, GFP_KERNEL);
1822            if (!buf)
1823                    return NULL;
1824            snprintf(buf, len - 1, "if");
1825            if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
1826                    const int pos = strlen(buf);
1827                    snprintf(buf + pos, len - pos - 1,
1828                             " task.type=execute_handler");
1829            }
1830            if (realpath) {
1831                    const int pos = strlen(buf);
1832                    snprintf(buf + pos, len - pos - 1, " exec.realpath=\"%s\"",
1833                             realpath);
1834                    kfree(realpath);
1835            }
1836            if (argv0) {
1837                    const int pos = strlen(buf);
1838                    snprintf(buf + pos, len - pos - 1, " exec.argv[0]=\"%s\"",
1839                             argv0);
1840            }
1841            cond = ccs_get_condition(buf);
1842            kfree(buf);
1843            return cond;
1844    }
1845    
1846  /* Wait queue for ccs_query_list. */  /* Wait queue for ccs_query_list. */
1847  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1848    
# Line 1721  static atomic_t ccs_query_observers = AT Line 1874  static atomic_t ccs_query_observers = AT
1874   * Returns 0 if the supervisor decided to permit the access request which   * Returns 0 if the supervisor decided to permit the access request which
1875   * violated the policy in enforcing mode, 1 if the supervisor decided to   * violated the policy in enforcing mode, 1 if the supervisor decided to
1876   * retry the access request which violated the policy in enforcing mode,   * retry the access request which violated the policy in enforcing mode,
1877   * -EPERM otherwise.   * 0 if it is not in enforcing mode, -EPERM otherwise.
1878   */   */
1879  int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)  int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)
1880  {  {
# Line 1735  int ccs_check_supervisor(struct ccs_requ Line 1888  int ccs_check_supervisor(struct ccs_requ
1888          char *header;          char *header;
1889          if (!r->domain)          if (!r->domain)
1890                  r->domain = ccs_current_domain();                  r->domain = ccs_current_domain();
1891            switch (r->mode) {
1892                    char *buffer;
1893                    struct ccs_condition *cond;
1894            case 1:
1895                    if (!ccs_domain_quota_ok(r))
1896                            return 0;
1897                    va_start(args, fmt);
1898                    len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
1899                    va_end(args);
1900                    buffer = kmalloc(len, GFP_KERNEL);
1901                    if (!buffer)
1902                            return 0;
1903                    va_start(args, fmt);
1904                    vsnprintf(buffer, len - 1, fmt, args);
1905                    va_end(args);
1906                    ccs_normalize_line(buffer);
1907                    if (r->ee && !strncmp(buffer, "allow_execute ", 14))
1908                            cond = ccs_get_execute_condition(r->ee);
1909                    else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
1910                            char str[] = "if task.type=execute_handler";
1911                            cond = ccs_get_condition(str);
1912                    } else
1913                            cond = NULL;
1914                    ccs_write_domain_policy2(buffer, r->domain, cond, false);
1915                    ccs_put_condition(cond);
1916                    kfree(buffer);
1917                    /* fall through */
1918            case 2:
1919                    return 0;
1920            }
1921          if (!atomic_read(&ccs_query_observers)) {          if (!atomic_read(&ccs_query_observers)) {
1922                  int i;                  int i;
1923                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
# Line 1755  int ccs_check_supervisor(struct ccs_requ Line 1938  int ccs_check_supervisor(struct ccs_requ
1938          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
1939          if (!ccs_query_entry)          if (!ccs_query_entry)
1940                  goto out;                  goto out;
1941            len = ccs_round2(len);
1942          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
1943          if (!ccs_query_entry->query)          if (!ccs_query_entry->query)
1944                  goto out;                  goto out;

Legend:
Removed from v.2894  
changed lines
  Added in v.2916

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