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

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

branches/ccs-patch/security/ccsecurity/policy_io.c revision 2911 by kumaneko, Sat Aug 15 12:21:38 2009 UTC trunk/1.7.x/ccs-patch/security/ccsecurity/policy_io.c revision 2975 by kumaneko, Tue Sep 1 05:34:46 2009 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
5   *   *
6   * Version: 1.7.0-pre   2009/08/08   * Version: 1.7.0-rc   2009/09/01
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 12  Line 12 
12    
13  #include "internal.h"  #include "internal.h"
14    
15  /* Lock for protecting ccs_profile->comment  */  static struct ccs_profile ccs_default_profile = {
16  static DEFINE_SPINLOCK(ccs_profile_comment_lock);          .learning = &ccs_default_profile.preference,
17            .permissive = &ccs_default_profile.preference,
18            .enforcing = &ccs_default_profile.preference,
19    #ifdef CONFIG_CCSECURITY_AUDIT
20            .audit = &ccs_default_profile.preference,
21            .preference.audit_max_grant_log = CONFIG_CCSECURITY_MAX_GRANT_LOG,
22            .preference.audit_max_reject_log = CONFIG_CCSECURITY_MAX_REJECT_LOG,
23    #endif
24            .preference.enforcing_penalty = 0,
25            .preference.enforcing_verbose = true,
26            .preference.learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY,
27            .preference.learning_verbose = false,
28            .preference.learning_exec_realpath = true,
29            .preference.learning_exec_argv0 = true,
30            .preference.learning_symlink_target = true,
31            .preference.permissive_verbose = true
32    };
33    
34    /* Profile table. Memory is allocated as needed. */
35    static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
36    
37  static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +  /* Lock for protecting "struct ccs_profile"->comment  */
38                                     CCS_MAX_CAPABILITY_INDEX + 1];  static DEFINE_SPINLOCK(ccs_profile_comment_lock);
39    
40  /* String table for functionality that takes 4 modes. */  /* String table for functionality that takes 4 modes. */
41  static const char *ccs_mode_4[4] = {  static const char *ccs_mode_4[4] = {
42          "disabled", "learning", "permissive", "enforcing"          "disabled", "learning", "permissive", "enforcing"
43  };  };
 /* String table for functionality that takes 2 modes. */  
 static const char *ccs_mode_2[4] = {  
         "disabled", "enabled", "enabled", "enabled"  
 };  
44    
45  /* Table for profile. */  /* String table for /proc/ccs/profile */
46  static struct {  static const char *ccs_mac_keywords[CCS_MAX_MAC_INDEX +
47          const char *keyword;                                      CCS_MAX_CAPABILITY_INDEX +
48          unsigned int current_value;                                      CCS_MAX_MAC_CATEGORY_INDEX] = {
49          const unsigned int max_value;          [CCS_MAC_FILE_EXECUTE]
50  } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {          = "file::execute",
51          [CCS_MAC_FOR_FILE]        = { "MAC_FOR_FILE",        0, 3 },          [CCS_MAC_FILE_OPEN]
52          [CCS_AUTOLEARN_EXEC_REALPATH] = { "AUTOLEARN_EXEC_REALPATH", 0, 1 },          = "file::open",
53          [CCS_AUTOLEARN_EXEC_ARGV0] = { "AUTOLEARN_EXEC_ARGV0", 0, 1 },          [CCS_MAC_FILE_CREATE]
54          [CCS_MAC_FOR_IOCTL]       = { "MAC_FOR_IOCTL",       0, 3 },          = "file::create",
55          [CCS_MAC_FOR_FILEATTR]    = { "MAC_FOR_FILEATTR",    0, 3 },          [CCS_MAC_FILE_UNLINK]
56          [CCS_MAC_FOR_ENV]         = { "MAC_FOR_ENV",         0, 3 },          = "file::unlink",
57          [CCS_MAC_FOR_NETWORK]     = { "MAC_FOR_NETWORK",     0, 3 },          [CCS_MAC_FILE_MKDIR]
58          [CCS_MAC_FOR_SIGNAL]      = { "MAC_FOR_SIGNAL",      0, 3 },          = "file::mkdir",
59          [CCS_MAC_FOR_NAMESPACE]   = { "MAC_FOR_NAMESPACE",   0, 3 },          [CCS_MAC_FILE_RMDIR]
60          [CCS_MAC_FOR_CAPABILITY]  = { "MAC_FOR_CAPABILITY",   0, 3 },          = "file::rmdir",
61          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },          [CCS_MAC_FILE_MKFIFO]
62          [CCS_MAX_ACCEPT_ENTRY]          = "file::mkfifo",
63          = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },          [CCS_MAC_FILE_MKSOCK]
64  #ifdef CONFIG_CCSECURITY_AUDIT          = "file::mksock",
65          [CCS_MAX_GRANT_LOG]          [CCS_MAC_FILE_TRUNCATE]
66          = { "MAX_GRANT_LOG", CONFIG_CCSECURITY_MAX_GRANT_LOG, INT_MAX },          = "file::truncate",
67          [CCS_MAX_REJECT_LOG]          [CCS_MAC_FILE_SYMLINK]
68          = { "MAX_REJECT_LOG", CONFIG_CCSECURITY_MAX_REJECT_LOG, INT_MAX },          = "file::symlink",
69  #endif          [CCS_MAC_FILE_REWRITE]
70          [CCS_VERBOSE]             = { "TOMOYO_VERBOSE",      1, 1 },          = "file::rewrite",
71          [CCS_SLEEP_PERIOD]          [CCS_MAC_FILE_MKBLOCK]
72          = { "SLEEP_PERIOD",        0, 3000 }, /* in 0.1 second */          = "file::mkblock",
73            [CCS_MAC_FILE_MKCHAR]
74            = "file::mkchar",
75            [CCS_MAC_FILE_LINK]
76            = "file::link",
77            [CCS_MAC_FILE_RENAME]
78            = "file::rename",
79            [CCS_MAC_FILE_CHMOD]
80            = "file::chmod",
81            [CCS_MAC_FILE_CHOWN]
82            = "file::chown",
83            [CCS_MAC_FILE_CHGRP]
84            = "file::chgrp",
85            [CCS_MAC_FILE_IOCTL]
86            = "file::ioctl",
87            [CCS_MAC_FILE_CHROOT]
88            = "file::chroot",
89            [CCS_MAC_FILE_MOUNT]
90            = "file::mount",
91            [CCS_MAC_FILE_UMOUNT]
92            = "file::umount",
93            [CCS_MAC_FILE_PIVOT_ROOT]
94            = "file::pivot_root",
95            [CCS_MAC_ENVIRON]
96            = "misc::env",
97            [CCS_MAC_NETWORK_UDP_BIND]
98            = "network::inet_udp_bind",
99            [CCS_MAC_NETWORK_UDP_CONNECT]
100            = "network::inet_udp_connect",
101            [CCS_MAC_NETWORK_TCP_BIND]
102            = "network::inet_tcp_bind",
103            [CCS_MAC_NETWORK_TCP_LISTEN]
104            = "network::inet_tcp_listen",
105            [CCS_MAC_NETWORK_TCP_CONNECT]
106            = "network::inet_tcp_connect",
107            [CCS_MAC_NETWORK_TCP_ACCEPT]
108            = "network::inet_tcp_accept",
109            [CCS_MAC_NETWORK_RAW_BIND]
110            = "network::inet_raw_bind",
111            [CCS_MAC_NETWORK_RAW_CONNECT]
112            = "network::inet_raw_connect",
113            [CCS_MAC_SIGNAL]
114            = "ipc::signal",
115            [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CREATE]
116            = "capability::inet_tcp_create",
117            [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_LISTEN]
118            = "capability::inet_tcp_listen",
119            [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CONNECT]
120            = "capability::inet_tcp_connect",
121            [CCS_MAX_MAC_INDEX + CCS_USE_INET_DGRAM_SOCKET]
122            = "capability::use_inet_udp",
123            [CCS_MAX_MAC_INDEX + CCS_USE_INET_RAW_SOCKET]
124            = "capability::use_inet_ip",
125            [CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET]
126            = "capability::use_route",
127            [CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET]
128            = "capability::use_packet",
129            [CCS_MAX_MAC_INDEX + CCS_SYS_MOUNT]
130            = "capability::SYS_MOUNT",
131            [CCS_MAX_MAC_INDEX + CCS_SYS_UMOUNT]
132            = "capability::SYS_UMOUNT",
133            [CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT]
134            = "capability::SYS_REBOOT",
135            [CCS_MAX_MAC_INDEX + CCS_SYS_CHROOT]
136            = "capability::SYS_CHROOT",
137            [CCS_MAX_MAC_INDEX + CCS_SYS_KILL]
138            = "capability::SYS_KILL",
139            [CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP]
140            = "capability::SYS_VHANGUP",
141            [CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME]
142            = "capability::SYS_TIME",
143            [CCS_MAX_MAC_INDEX + CCS_SYS_NICE]
144            = "capability::SYS_NICE",
145            [CCS_MAX_MAC_INDEX + CCS_SYS_SETHOSTNAME]
146            = "capability::SYS_SETHOSTNAME",
147            [CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE]
148            = "capability::use_kernel_module",
149            [CCS_MAX_MAC_INDEX + CCS_CREATE_FIFO]
150            = "capability::create_fifo",
151            [CCS_MAX_MAC_INDEX + CCS_CREATE_BLOCK_DEV]
152            = "capability::create_block_dev",
153            [CCS_MAX_MAC_INDEX + CCS_CREATE_CHAR_DEV]
154            = "capability::create_char_dev",
155            [CCS_MAX_MAC_INDEX + CCS_CREATE_UNIX_SOCKET]
156            = "capability::create_unix_socket",
157            [CCS_MAX_MAC_INDEX + CCS_SYS_LINK]
158            = "capability::SYS_LINK",
159            [CCS_MAX_MAC_INDEX + CCS_SYS_SYMLINK]
160            = "capability::SYS_SYMLINK",
161            [CCS_MAX_MAC_INDEX + CCS_SYS_RENAME]
162            = "capability::SYS_RENAME",
163            [CCS_MAX_MAC_INDEX + CCS_SYS_UNLINK]
164            = "capability::SYS_UNLINK",
165            [CCS_MAX_MAC_INDEX + CCS_SYS_CHMOD]
166            = "capability::SYS_CHMOD",
167            [CCS_MAX_MAC_INDEX + CCS_SYS_CHOWN]
168            = "capability::SYS_CHOWN",
169            [CCS_MAX_MAC_INDEX + CCS_SYS_IOCTL]
170            = "capability::SYS_IOCTL",
171            [CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD]
172            = "capability::SYS_KEXEC_LOAD",
173            [CCS_MAX_MAC_INDEX + CCS_SYS_PIVOT_ROOT]
174            = "capability::SYS_PIVOT_ROOT",
175            [CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE]
176            = "capability::SYS_PTRACE",
177            [CCS_MAX_MAC_INDEX + CCS_CONCEAL_MOUNT]
178            = "capability::conceal_mount",
179            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
180             + CCS_MAC_CATEGORY_FILE] = "file",
181            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
182             + CCS_MAC_CATEGORY_NETWORK] = "network",
183            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
184             + CCS_MAC_CATEGORY_MISC] = "misc",
185            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
186             + CCS_MAC_CATEGORY_IPC] = "ipc",
187            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
188             + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
189  };  };
190    
191  /* Permit policy management by non-root user? */  /* Permit policy management by non-root user? */
192  static bool ccs_manage_by_non_root;  static bool ccs_manage_by_non_root;
193    
194  /**  /**
195   * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.   * ccs_cap2keyword - Convert capability operation to capability name.
196   *   *
197   * @str: Unused.   * @operation: The capability index.
198   *   *
199   * Returns 0.   * Returns the name of the specified capability's name.
200   */   */
201  static int __init ccs_quiet_setup(char *str)  const char *ccs_cap2keyword(const u8 operation)
202  {  {
203          ccs_control_array[CCS_VERBOSE].current_value = 0;          return operation < CCS_MAX_CAPABILITY_INDEX
204          return 0;                  ? ccs_mac_keywords[CCS_MAX_MAC_INDEX + operation] + 12 : NULL;
205  }  }
206    
207  __setup("CCS_QUIET", ccs_quiet_setup);  /**
208     * ccs_yesno - Return "yes" or "no".
209     *
210     * @value: Bool value.
211     */
212    static const char *ccs_yesno(const unsigned int value)
213    {
214            return value ? "yes" : "no";
215    }
216    
217  /**  /**
218   * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.   * ccs_io_printf - Transactional printf() to "struct ccs_io_buffer" structure.
# Line 114  static struct ccs_profile *ccs_find_or_a Line 253  static struct ccs_profile *ccs_find_or_a
253  {  {
254          struct ccs_profile *ptr;          struct ccs_profile *ptr;
255          struct ccs_profile *entry;          struct ccs_profile *entry;
         int i;  
256          if (profile >= CCS_MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
257                  return NULL;                  return NULL;
258          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
# Line 125  static struct ccs_profile *ccs_find_or_a Line 263  static struct ccs_profile *ccs_find_or_a
263          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
264          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
265                  ptr = entry;                  ptr = entry;
266                  for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)  #ifdef CONFIG_CCSECURITY_AUDIT
267                          ptr->value[i] = ccs_control_array[i].current_value;                  ptr->audit = &ccs_default_profile.preference;
268                  /*  #endif
269                   * Needn't to initialize "ptr->capability_value"                  ptr->learning = &ccs_default_profile.preference;
270                   * because they are always 0.                  ptr->permissive = &ccs_default_profile.preference;
271                   */                  ptr->enforcing = &ccs_default_profile.preference;
272                    ptr->default_config = CCS_CONFIG_DISABLED |
273                            CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
274                    memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
275                           sizeof(ptr->config));
276                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
277                  ccs_profile_ptr[profile] = ptr;                  ccs_profile_ptr[profile] = ptr;
278                  entry = NULL;                  entry = NULL;
# Line 141  static struct ccs_profile *ccs_find_or_a Line 283  static struct ccs_profile *ccs_find_or_a
283  }  }
284    
285  /**  /**
286     * ccs_profile - Find a profile.
287     *
288     * @profile: Profile number to find.
289     *
290     * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
291     */
292    struct ccs_profile *ccs_profile(const u8 profile)
293    {
294            struct ccs_profile *ptr = ccs_profile_ptr[profile];
295            if (!ccs_policy_loaded)
296                    return &ccs_default_profile;
297            BUG_ON(!ptr);
298            return ptr;
299    }
300    
301    /**
302   * ccs_write_profile - Write profile table.   * ccs_write_profile - Write profile table.
303   *   *
304   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 151  static int ccs_write_profile(struct ccs_ Line 309  static int ccs_write_profile(struct ccs_
309  {  {
310          char *data = head->write_buf;          char *data = head->write_buf;
311          unsigned int i;          unsigned int i;
312          unsigned int value;          int value;
313            int mode;
314            u8 config;
315            bool use_default = false;
316          char *cp;          char *cp;
317          struct ccs_profile *ccs_profile;          struct ccs_profile *profile;
318          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
319          if (data != cp) {          if (data == cp) {
320                    profile = &ccs_default_profile;
321            } else {
322                  if (*cp != '-')                  if (*cp != '-')
323                          return -EINVAL;                          return -EINVAL;
324                  data = cp + 1;                  data = cp + 1;
325                    profile = ccs_find_or_assign_new_profile(i);
326                    if (!profile)
327                            return -EINVAL;
328          }          }
         ccs_profile = ccs_find_or_assign_new_profile(i);  
         if (!ccs_profile)  
                 return -EINVAL;  
329          cp = strchr(data, '=');          cp = strchr(data, '=');
330          if (!cp)          if (!cp)
331                  return -EINVAL;                  return -EINVAL;
332          *cp = '\0';          *cp++ = '\0';
333            if (profile != &ccs_default_profile)
334                    use_default = strstr(cp, "use_default") != NULL;
335            if (strstr(cp, "verbose=yes"))
336                    value = 1;
337            else if (strstr(cp, "verbose=no"))
338                    value = 0;
339            else
340                    value = -1;
341    #ifdef CONFIG_CCSECURITY_AUDIT
342            if (!strcmp(data, "PREFERENCE::audit")) {
343                    char *cp2;
344                    if (use_default) {
345                            profile->audit = &ccs_default_profile.preference;
346                            return 0;
347                    }
348                    profile->audit = &profile->preference;
349                    cp2 = strstr(cp, "max_grant_log=");
350                    if (cp2)
351                            sscanf(cp2 + 14, "%u",
352                                   &profile->preference.audit_max_grant_log);
353                    cp2 = strstr(cp, "max_reject_log=");
354                    if (cp2)
355                            sscanf(cp2 + 15, "%u",
356                                   &profile->preference.audit_max_reject_log);
357                    return 0;
358            }
359    #endif
360            if (!strcmp(data, "PREFERENCE::enforcing")) {
361                    char *cp2;
362                    if (use_default) {
363                            profile->enforcing = &ccs_default_profile.preference;
364                            return 0;
365                    }
366                    profile->enforcing = &profile->preference;
367                    if (value >= 0)
368                            profile->preference.enforcing_verbose = value;
369                    cp2 = strstr(cp, "penalty=");
370                    if (cp2)
371                            sscanf(cp2 + 8, "%u",
372                                   &profile->preference.enforcing_penalty);
373                    return 0;
374            }
375            if (!strcmp(data, "PREFERENCE::permissive")) {
376                    if (use_default) {
377                            profile->permissive = &ccs_default_profile.preference;
378                            return 0;
379                    }
380                    profile->permissive = &profile->preference;
381                    if (value >= 0)
382                            profile->preference.permissive_verbose = value;
383                    return 0;
384            }
385            if (!strcmp(data, "PREFERENCE::learning")) {
386                    char *cp2;
387                    if (use_default) {
388                            profile->learning = &ccs_default_profile.preference;
389                            return 0;
390                    }
391                    profile->learning = &profile->preference;
392                    if (value >= 0)
393                            profile->preference.learning_verbose = value;
394                    cp2 = strstr(cp, "max_entry=");
395                    if (cp2)
396                            sscanf(cp2 + 10, "%u",
397                                   &profile->preference.learning_max_entry);
398                    if (strstr(cp, "exec.realpath=yes"))
399                            profile->preference.learning_exec_realpath = true;
400                    else if (strstr(cp, "exec.realpath=no"))
401                            profile->preference.learning_exec_realpath = false;
402                    if (strstr(cp, "exec.argv0=yes"))
403                            profile->preference.learning_exec_argv0 = true;
404                    else if (strstr(cp, "exec.argv0=no"))
405                            profile->preference.learning_exec_argv0 = false;
406                    if (strstr(cp, "symlink.target=yes"))
407                            profile->preference.learning_symlink_target = true;
408                    else if (strstr(cp, "symlink.target=no"))
409                            profile->preference.learning_symlink_target = false;
410                    return 0;
411            }
412            if (profile == &ccs_default_profile)
413                    return -EINVAL;
414          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
415                  const struct ccs_path_info *new_comment                  const struct ccs_path_info *new_comment = ccs_get_name(cp);
                         = ccs_get_name(cp + 1);  
416                  const struct ccs_path_info *old_comment;                  const struct ccs_path_info *old_comment;
417                  /* Protect reader from ccs_put_name(). */                  /* Protect reader from ccs_put_name(). */
                 /***** CRITICAL SECTION START *****/  
418                  spin_lock(&ccs_profile_comment_lock);                  spin_lock(&ccs_profile_comment_lock);
419                  old_comment = ccs_profile->comment;                  old_comment = profile->comment;
420                  ccs_profile->comment = new_comment;                  profile->comment = new_comment;
421                  spin_unlock(&ccs_profile_comment_lock);                  spin_unlock(&ccs_profile_comment_lock);
                 /***** CRITICAL SECTION END *****/  
422                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
                 ccs_profile_entry_used[0] = true;  
423                  return 0;                  return 0;
424          }          }
425          if (!strcmp(data, CCS_KEYWORD_CAPABILITIES)) {          if (!strcmp(data, "CONFIG")) {
426                  unsigned char capabilities[CCS_MAX_CAPABILITY_INDEX];                  i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
427                  memset(capabilities, 0, sizeof(capabilities));                          + CCS_MAX_MAC_CATEGORY_INDEX;
428                  cp++;                  config = profile->default_config;
429                  while (1) {          } else if (ccs_str_starts(&data, "CONFIG::")) {
430                          char *cp2 = strchr(cp, ' ');                  config = 0;
431                          if (cp2)                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
432                                  *cp2 = '\0';                               + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
433                          for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {                          if (strcmp(data, ccs_mac_keywords[i]))
434                                  if (strcmp(cp, ccs_capability_list[i]))                                  continue;
435                                          continue;                          config = profile->config[i];
436                                  capabilities[i] = 1;                          break;
                         }  
                         if (!cp2)  
                                 break;  
                         cp = cp2 + 1;  
437                  }                  }
438                  for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++)                  if (i == CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
439                          ccs_profile->enabled_capabilities[i] = capabilities[i];                      + CCS_MAX_MAC_CATEGORY_INDEX)
440                  return 0;                          return -EINVAL;
441            } else {
442                    return -EINVAL;
443          }          }
444          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {          if (use_default) {
445                  if (strcmp(data, ccs_control_array[i].keyword))                  config = CCS_CONFIG_USE_DEFAULT;
446                          continue;          } else {
447                  if (sscanf(cp + 1, "%u", &value) != 1) {                  for (mode = 3; mode >= 0; mode--)
448                          int j;                          if (strstr(cp, ccs_mode_4[mode]))
449                          const char **modes;                                  /*
450                          switch (i) {                                   * Update lower 3 bits in order to distinguish
451                          case CCS_AUTOLEARN_EXEC_REALPATH:                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
452                          case CCS_AUTOLEARN_EXEC_ARGV0:                                   */
453                          case CCS_RESTRICT_AUTOBIND:                                  config = (config & ~7) | mode;
454                          case CCS_VERBOSE:  #ifdef CONFIG_CCSECURITY_AUDIT
455                                  modes = ccs_mode_2;                  if (config != CCS_CONFIG_USE_DEFAULT) {
456                                  break;                          if (strstr(cp, "grant_log=yes"))
457                          default:                                  config |= CCS_CONFIG_WANT_GRANT_LOG;
458                                  modes = ccs_mode_4;                          else if (strstr(cp, "grant_log=no"))
459                                  break;                                  config &= ~CCS_CONFIG_WANT_GRANT_LOG;
460                          }                          if (strstr(cp, "reject_log=yes"))
461                          for (j = 0; j < 4; j++) {                                  config |= CCS_CONFIG_WANT_REJECT_LOG;
462                                  if (strcmp(cp + 1, modes[j]))                          else if (strstr(cp, "reject_log=no"))
463                                          continue;                                  config &= ~CCS_CONFIG_WANT_REJECT_LOG;
                                 value = j;  
                                 break;  
                         }  
                         if (j == 4)  
                                 return -EINVAL;  
                 } else if (value > ccs_control_array[i].max_value) {  
                         value = ccs_control_array[i].max_value;  
464                  }                  }
465                  ccs_profile->value[i] = value;  #endif
                 ccs_profile_entry_used[i + 1] = true;  
                 return 0;  
         }  
         return -EINVAL;  
 }  
   
 static bool ccs_print_capability_list(struct ccs_io_buffer *head, u8 index)  
 {  
         const int pos = head->read_avail;  
         int i;  
         const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];  
         if (!ccs_io_printf(head, "%u-" CCS_KEYWORD_CAPABILITIES "={", index))  
                 return false;  
         for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {  
                 if (!ccs_profile->enabled_capabilities[i])  
                         continue;  
                 if (!ccs_io_printf(head, " %s", ccs_capability_list[i]))  
                         goto out;  
466          }          }
467          if (!ccs_io_printf(head, " }\n"))          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
468                  goto out;              + CCS_MAX_MAC_CATEGORY_INDEX)
469          return true;                  profile->config[i] = config;
470   out:          else if (config != CCS_CONFIG_USE_DEFAULT)
471          head->read_avail = pos;                  profile->default_config = config;
472          return false;          return 0;
473  }  }
474    
475  /**  /**
476   * ccs_read_profile - Read profile table.   * ccs_read_profile - Read profile table.
477   *   *
478   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns 0.  
479   */   */
480  static int ccs_read_profile(struct ccs_io_buffer *head)  static void ccs_read_profile(struct ccs_io_buffer *head)
481  {  {
482          static const int ccs_total = CCS_MAX_CONTROL_INDEX + 2;          int index;
         int step;  
483          if (head->read_eof)          if (head->read_eof)
484                  return 0;                  return;
485          for (step = head->read_step; step < CCS_MAX_PROFILES * ccs_total;          if (head->read_bit)
486               step++) {                  goto body;
487                  const u8 index = step / ccs_total;          ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090827");
488                  u8 type = step % ccs_total;  #ifdef CONFIG_CCSECURITY_AUDIT
489                  const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];          ccs_io_printf(head, "PREFERENCE::audit={ max_grant_log=%u "
490                  head->read_step = step;                        "max_reject_log=%u }\n",
491                  if (!ccs_profile)                        ccs_default_profile.preference.audit_max_grant_log,
492                          continue;                        ccs_default_profile.preference.audit_max_reject_log);
493                  if (!ccs_profile_entry_used[type])  #endif
494                          continue;          ccs_io_printf(head, "PREFERENCE::learning={ verbose=%s max_entry=%u "
495                  if (!type) { /* Print profile' comment tag. */                        "exec.realpath=%s exec.argv0=%s symlink.target=%s }\n",
496                          bool done;                        ccs_yesno(ccs_default_profile.preference.
497                          /***** CRITICAL SECTION START *****/                                  learning_verbose),
498                          spin_lock(&ccs_profile_comment_lock);                        ccs_default_profile.preference.learning_max_entry,
499                          done = ccs_io_printf(head, "%u-COMMENT=%s\n",                        ccs_yesno(ccs_default_profile.preference.
500                                               index, ccs_profile->comment ?                                  learning_exec_realpath),
501                                               ccs_profile->comment->name : "");                        ccs_yesno(ccs_default_profile.preference.
502                          spin_unlock(&ccs_profile_comment_lock);                                  learning_exec_argv0),
503                          /***** CRITICAL SECTION END *****/                        ccs_yesno(ccs_default_profile.preference.
504                          if (!done)                                  learning_symlink_target));
505                                  break;          ccs_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n",
506                          continue;                        ccs_yesno(ccs_default_profile.preference.
507                  }                                  permissive_verbose));
508                  if (type == 1) {          ccs_io_printf(head, "PREFERENCE::enforcing={ verbose=%s penalty=%u "
509                          if (!ccs_print_capability_list(head, index))                        "}\n",
510                                  break;                        ccs_yesno(ccs_default_profile.preference.
511                                    enforcing_verbose),
512                          ccs_default_profile.preference.enforcing_penalty);
513            head->read_bit = 1;
514     body:
515            for (index = head->read_step; index < CCS_MAX_PROFILES; index++) {
516                    bool done;
517                    u8 config;
518                    int i;
519                    int pos;
520                    const struct ccs_profile *profile = ccs_profile_ptr[index];
521                    head->read_step = index;
522                    if (!profile)
523                          continue;                          continue;
524                    pos = head->read_avail;
525                    spin_lock(&ccs_profile_comment_lock);
526                    done = ccs_io_printf(head, "%u-COMMENT=%s\n", index,
527                                         profile->comment ? profile->comment->name
528                                         : "");
529                    spin_unlock(&ccs_profile_comment_lock);
530                    if (!done)
531                            goto out;
532                    config = profile->default_config;
533    #ifdef CONFIG_CCSECURITY_AUDIT
534                    if (!ccs_io_printf(head, "%u-CONFIG={ mode=%s grant_log=%s "
535                                       "reject_log=%s }\n", index,
536                                       ccs_mode_4[config & 3],
537                                       ccs_yesno(config &
538                                                 CCS_CONFIG_WANT_GRANT_LOG),
539                                       ccs_yesno(config &
540                                                 CCS_CONFIG_WANT_REJECT_LOG)))
541                            goto out;
542    #else
543                    if (!ccs_io_printf(head, "%u-CONFIG={ mode=%s }\n", index,
544                                       ccs_mode_4[config & 3]))
545                            goto out;
546    #endif
547                    for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
548                                 + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
549    #ifdef CONFIG_CCSECURITY_AUDIT
550                            const char *g;
551                            const char *r;
552    #endif
553                            config = profile->config[i];
554                            if (config == CCS_CONFIG_USE_DEFAULT)
555                                    continue;
556    #ifdef CONFIG_CCSECURITY_AUDIT
557                            g = ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG);
558                            r = ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG);
559                            if (!ccs_io_printf(head, "%u-CONFIG::%s={ mode=%s "
560                                               "grant_log=%s reject_log=%s }\n",
561                                               index, ccs_mac_keywords[i],
562                                               ccs_mode_4[config & 3], g, r))
563                                    goto out;
564    #else
565                            if (!ccs_io_printf(head, "%u-CONFIG::%s={ mode=%s }\n",
566                                               index, ccs_mac_keywords[i],
567                                               ccs_mode_4[config & 3]))
568                                    goto out;
569    #endif
570                  }                  }
571                  type -= 2;  #ifdef CONFIG_CCSECURITY_AUDIT
572                  {                  if (profile->audit != &ccs_default_profile.preference &&
573                          const unsigned int value = ccs_profile->value[type];                      !ccs_io_printf(head, "%u-PREFERENCE::audit={ "
574                          const char **modes = NULL;                                     "max_grant_log=%u max_reject_log=%u }\n",
575                          const char *keyword = ccs_control_array[type].keyword;                                     index,
576                          switch (ccs_control_array[type].max_value) {                                     profile->preference.audit_max_grant_log,
577                          case 3:                                     profile->preference.audit_max_reject_log))
578                                  modes = ccs_mode_4;                          goto out;
579                                  break;  #endif
580                          case 1:                  if (profile->learning != &ccs_default_profile.preference &&
581                                  modes = ccs_mode_2;                      !ccs_io_printf(head, "%u-PREFERENCE::learning={ "
582                                  break;                                     "verbose=%s max_entry=%u exec.realpath=%s "
583                          }                                     "exec.argv0=%s symlink.target=%s }\n",
584                          if (modes) {                                     index,
585                                  if (!ccs_io_printf(head, "%u-%s=%s\n", index,                                     ccs_yesno(profile->preference.
586                                                     keyword, modes[value]))                                               learning_verbose),
587                                          break;                                     profile->preference.learning_max_entry,
588                          } else {                                     ccs_yesno(profile->preference.
589                                  if (!ccs_io_printf(head, "%u-%s=%u\n", index,                                               learning_exec_realpath),
590                                                     keyword, value))                                     ccs_yesno(profile->preference.
591                                          break;                                               learning_exec_argv0),
592                          }                                     ccs_yesno(profile->preference.
593                  }                                               learning_symlink_target)))
594                            goto out;
595                    if (profile->permissive != &ccs_default_profile.preference &&
596                        !ccs_io_printf(head, "%u-PREFERENCE::permissive={ "
597                                       "verbose=%s }\n", index,
598                                       ccs_yesno(profile->preference.
599                                                 permissive_verbose)))
600                            goto out;
601                    if (profile->enforcing != &ccs_default_profile.preference &&
602                        !ccs_io_printf(head, "%u-PREFERENCE::enforcing={ "
603                                       "verbose=%s penalty=%u }\n", index,
604                                       ccs_yesno(profile->preference.
605                                                 enforcing_verbose),
606                                       profile->preference.enforcing_penalty))
607                            goto out;
608                    continue;
609     out:
610                    head->read_avail = pos;
611                    break;
612          }          }
613          if (step == CCS_MAX_PROFILES * ccs_total)          if (index == CCS_MAX_PROFILES)
614                  head->read_eof = true;                  head->read_eof = true;
         return 0;  
615  }  }
616    
617  /* The list for "struct ccs_policy_manager_entry". */  /* The list for "struct ccs_policy_manager_entry". */
# Line 401  static int ccs_write_manager_policy(stru Line 686  static int ccs_write_manager_policy(stru
686   *   *
687   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
688   *   *
  * Returns 0.  
  *  
689   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
690   */   */
691  static int ccs_read_manager_policy(struct ccs_io_buffer *head)  static void ccs_read_manager_policy(struct ccs_io_buffer *head)
692  {  {
693          struct list_head *pos;          struct list_head *pos;
         ccs_check_read_lock();  
694          if (head->read_eof)          if (head->read_eof)
695                  return 0;                  return;
696          list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {          list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
697                  struct ccs_policy_manager_entry *ptr;                  struct ccs_policy_manager_entry *ptr;
698                  ptr = list_entry(pos, struct ccs_policy_manager_entry, list);                  ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
699                  if (ptr->is_deleted)                  if (ptr->is_deleted)
700                          continue;                          continue;
701                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
702                          return 0;                          return;
703          }          }
704          head->read_eof = true;          head->read_eof = true;
         return 0;  
705  }  }
706    
707  /**  /**
# Line 439  static bool ccs_is_policy_manager(void) Line 720  static bool ccs_is_policy_manager(void)
720          const struct ccs_path_info *domainname          const struct ccs_path_info *domainname
721                  = ccs_current_domain()->domainname;                  = ccs_current_domain()->domainname;
722          bool found = false;          bool found = false;
         ccs_check_read_lock();  
723          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
724                  return true;                  return true;
725          if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)          if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
# Line 520  static bool ccs_is_select_one(struct ccs Line 800  static bool ccs_is_select_one(struct ccs
800  {  {
801          unsigned int pid;          unsigned int pid;
802          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
803          ccs_check_read_lock();          bool global_pid = false;
804          if (!strcmp(data, "allow_execute")) {          if (!strcmp(data, "allow_execute")) {
805                  head->read_execute_only = true;                  head->read_execute_only = true;
806                  return true;                  return true;
807          }          }
808          if (sscanf(data, "pid=%u", &pid) == 1) {          if (sscanf(data, "pid=%u", &pid) == 1 ||
809                (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
810                  struct task_struct *p;                  struct task_struct *p;
                 /***** CRITICAL SECTION START *****/  
811                  read_lock(&tasklist_lock);                  read_lock(&tasklist_lock);
812    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
813                    if (global_pid)
814                            p = find_task_by_pid_ns(pid, &init_pid_ns);
815                    else
816                            p = find_task_by_vpid(pid);
817    #else
818                  p = find_task_by_pid(pid);                  p = find_task_by_pid(pid);
819    #endif
820                  if (p)                  if (p)
821                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
822                  read_unlock(&tasklist_lock);                  read_unlock(&tasklist_lock);
                 /***** CRITICAL SECTION END *****/  
823          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
824                  if (ccs_is_domain_def(data + 7))                  if (ccs_is_domain_def(data + 7))
825                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
# Line 631  static int ccs_write_domain_policy(struc Line 917  static int ccs_write_domain_policy(struc
917    
918          if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1          if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
919              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
920                  if (ccs_profile_ptr[profile] || !ccs_policy_loaded)                  if (ccs_profile(profile))
921                          domain->profile = (u8) profile;                          domain->profile = (u8) profile;
922                  return 0;                  return 0;
923          }          }
# Line 655  static int ccs_write_domain_policy(struc Line 941  static int ccs_write_domain_policy(struc
941          return error;          return error;
942  }  }
943    
944    /**
945     * ccs_print_name_union - Print a ccs_name_union.
946     *
947     * @head: Pointer to "struct ccs_io_buffer".
948     * @ptr:  Pointer to "struct ccs_name_union".
949     *
950     * Returns true on success, false otherwise.
951     */
952  static bool ccs_print_name_union(struct ccs_io_buffer *head,  static bool ccs_print_name_union(struct ccs_io_buffer *head,
953                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
954  {  {
# Line 667  static bool ccs_print_name_union(struct Line 961  static bool ccs_print_name_union(struct
961          return ccs_io_printf(head, " %s", ptr->filename->name);          return ccs_io_printf(head, " %s", ptr->filename->name);
962  }  }
963    
964    /**
965     * ccs_print_name_union_quoted - Print a ccs_name_union with double quotes.
966     *
967     * @head: Pointer to "struct ccs_io_buffer".
968     * @ptr:  Pointer to "struct ccs_name_union".
969     *
970     * Returns true on success, false otherwise.
971     */
972  static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head,  static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head,
973                                          const struct ccs_name_union *ptr)                                          const struct ccs_name_union *ptr)
974  {  {
# Line 676  static bool ccs_print_name_union_quoted( Line 978  static bool ccs_print_name_union_quoted(
978          return ccs_io_printf(head, "\"%s\"", ptr->filename->name);          return ccs_io_printf(head, "\"%s\"", ptr->filename->name);
979  }  }
980    
981    /**
982     * ccs_print_number_union_common - Print a ccs_number_union.
983     *
984     * @head:       Pointer to "struct ccs_io_buffer".
985     * @ptr:        Pointer to "struct ccs_number_union".
986     * @need_space: True if a space character is needed.
987     *
988     * Returns true on success, false otherwise.
989     */
990  static bool ccs_print_number_union_common(struct ccs_io_buffer *head,  static bool ccs_print_number_union_common(struct ccs_io_buffer *head,
991                                            const struct ccs_number_union *ptr,                                            const struct ccs_number_union *ptr,
992                                            const bool need_space)                                            const bool need_space)
# Line 719  static bool ccs_print_number_union_commo Line 1030  static bool ccs_print_number_union_commo
1030          }          }
1031  }  }
1032    
1033    /**
1034     * ccs_print_number_union - Print a ccs_number_union.
1035     *
1036     * @head:       Pointer to "struct ccs_io_buffer".
1037     * @ptr:        Pointer to "struct ccs_number_union".
1038     *
1039     * Returns true on success, false otherwise.
1040     */
1041  bool ccs_print_number_union(struct ccs_io_buffer *head,  bool ccs_print_number_union(struct ccs_io_buffer *head,
1042                              const struct ccs_number_union *ptr)                              const struct ccs_number_union *ptr)
1043  {  {
1044          return ccs_print_number_union_common(head, ptr, true);          return ccs_print_number_union_common(head, ptr, true);
1045  }  }
1046    
1047    /**
1048     * ccs_print_number_union_nospace - Print a ccs_number_union without a space character.
1049     *
1050     * @head:       Pointer to "struct ccs_io_buffer".
1051     * @ptr:        Pointer to "struct ccs_number_union".
1052     *
1053     * Returns true on success, false otherwise.
1054     */
1055  static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head,  static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1056                                             const struct ccs_number_union *ptr)                                             const struct ccs_number_union *ptr)
1057  {  {
# Line 843  static bool ccs_print_condition(struct c Line 1170  static bool ccs_print_condition(struct c
1170  }  }
1171    
1172  /**  /**
1173   * ccs_print_single_path_acl - Print a single path ACL entry.   * ccs_print_path_acl - Print a single path ACL entry.
1174   *   *
1175   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1176   * @ptr:  Pointer to "struct ccs_single_path_acl_record".   * @ptr:  Pointer to "struct ccs_path_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_single_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_acl(struct ccs_io_buffer *head,
1182                                        struct ccs_single_path_acl_record *ptr,                                 struct ccs_path_acl *ptr,
1183                                        const struct ccs_condition *cond)                                 const struct ccs_condition *cond)
1184  {  {
1185          int pos;          int pos;
1186          u8 bit;          u8 bit;
1187          const u16 perm = ptr->perm;          const u16 perm = ptr->perm;
1188          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;  
1189                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1190                          continue;                          continue;
1191                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE_ACL)                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE)
1192                          continue;                          continue;
1193                  /* Print "read/write" instead of "read" and "write". */                  /* Print "read/write" instead of "read" and "write". */
1194                  if ((bit == CCS_TYPE_READ_ACL || bit == CCS_TYPE_WRITE_ACL)                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
1195                      && (perm & (1 << CCS_TYPE_READ_WRITE_ACL)))                      && (perm & (1 << CCS_TYPE_READ_WRITE)))
1196                          continue;                          continue;
                 msg = ccs_sp2keyword(bit);  
1197                  pos = head->read_avail;                  pos = head->read_avail;
1198                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||
1199                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1200                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, cond)) {
1201                          head->read_bit = bit;                          head->read_bit = bit;
# Line 883  static bool ccs_print_single_path_acl(st Line 1208  static bool ccs_print_single_path_acl(st
1208  }  }
1209    
1210  /**  /**
1211   * ccs_print_mkdev_acl - Print a mkdev ACL entry.   * ccs_print_path_number3_acl - Print a path_number3 ACL entry.
1212   *   *
1213   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1214   * @ptr:  Pointer to "struct ccs_mkdev_acl_record".   * @ptr:  Pointer to "struct ccs_path_number3_acl".
1215   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1216   *   *
1217   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1218   */   */
1219  static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number3_acl(struct ccs_io_buffer *head,
1220                                  struct ccs_mkdev_acl_record *ptr,                                         struct ccs_path_number3_acl *ptr,
1221                                  const struct ccs_condition *cond)                                         const struct ccs_condition *cond)
1222  {  {
1223          int pos;          int pos;
1224          u8 bit;          u8 bit;
1225          const u16 perm = ptr->perm;          const u16 perm = ptr->perm;
1226          for (bit = head->read_bit; bit < CCS_MAX_MKDEV_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER3_OPERATION;
1227                  const char *msg;               bit++) {
1228                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1229                          continue;                          continue;
                 msg = ccs_mkdev2keyword(bit);  
1230                  pos = head->read_avail;                  pos = head->read_avail;
1231                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1232                                       ccs_path_number32keyword(bit)) ||
1233                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1234                        !ccs_print_number_union(head, &ptr->mode) ||
1235                      !ccs_print_number_union(head, &ptr->major) ||                      !ccs_print_number_union(head, &ptr->major) ||
1236                      !ccs_print_number_union(head, &ptr->minor) ||                      !ccs_print_number_union(head, &ptr->minor) ||
1237                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, cond)) {
# Line 919  static bool ccs_print_mkdev_acl(struct c Line 1245  static bool ccs_print_mkdev_acl(struct c
1245  }  }
1246    
1247  /**  /**
1248   * ccs_print_double_path_acl - Print a double path ACL entry.   * ccs_print_path2_acl - Print a path2 ACL entry.
1249   *   *
1250   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1251   * @ptr:  Pointer to "struct ccs_double_path_acl_record".   * @ptr:  Pointer to "struct ccs_path2_acl".
1252   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1253   *   *
1254   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1255   */   */
1256  static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_path2_acl(struct ccs_io_buffer *head,
1257                                        struct ccs_double_path_acl_record *ptr,                                  struct ccs_path2_acl *ptr,
1258                                        const struct ccs_condition *cond)                                  const struct ccs_condition *cond)
1259  {  {
1260          int pos;          int pos;
1261          u8 bit;          u8 bit;
1262          const u8 perm = ptr->perm;          const u8 perm = ptr->perm;
1263          for (bit = head->read_bit; bit < CCS_MAX_DOUBLE_PATH_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH2_OPERATION; bit++) {
                 const char *msg;  
1264                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1265                          continue;                          continue;
                 msg = ccs_dp2keyword(bit);  
1266                  pos = head->read_avail;                  pos = head->read_avail;
1267                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1268                                       ccs_path22keyword(bit)) ||
1269                      !ccs_print_name_union(head, &ptr->name1) ||                      !ccs_print_name_union(head, &ptr->name1) ||
1270                      !ccs_print_name_union(head, &ptr->name2) ||                      !ccs_print_name_union(head, &ptr->name2) ||
1271                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, cond)) {
# Line 954  static bool ccs_print_double_path_acl(st Line 1279  static bool ccs_print_double_path_acl(st
1279  }  }
1280    
1281  /**  /**
1282   * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.   * ccs_print_path_number_acl - Print a path_number ACL entry.
1283   *   *
1284   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1285   * @ptr:  Pointer to "struct ccs_path_number_acl_record".   * @ptr:  Pointer to "struct ccs_path_number_acl".
1286   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1287   *   *
1288   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1289   */   */
1290  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
1291                                        struct ccs_path_number_acl_record *ptr,                                        struct ccs_path_number_acl *ptr,
1292                                        const struct ccs_condition *cond)                                        const struct ccs_condition *cond)
1293  {  {
1294          int pos;          int pos;
1295          u8 bit;          u8 bit;
1296          const u8 perm = ptr->perm;          const u8 perm = ptr->perm;
1297          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION;
1298                  const char *msg;               bit++) {
1299                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1300                          continue;                          continue;
                 msg = ccs_path_number2keyword(bit);  
1301                  pos = head->read_avail;                  pos = head->read_avail;
1302                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1303                                       ccs_path_number2keyword(bit)) ||
1304                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1305                      !ccs_print_number_union(head, &ptr->number) ||                      !ccs_print_number_union(head, &ptr->number) ||
1306                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, cond)) {
# Line 992  static bool ccs_print_path_number_acl(st Line 1317  static bool ccs_print_path_number_acl(st
1317   * ccs_print_env_acl - Print an evironment variable name's ACL entry.   * ccs_print_env_acl - Print an evironment variable name's ACL entry.
1318   *   *
1319   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1320   * @ptr:  Pointer to "struct ccs_env_acl_record".   * @ptr:  Pointer to "struct ccs_env_acl".
1321   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1322   *   *
1323   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1324   */   */
1325  static bool ccs_print_env_acl(struct ccs_io_buffer *head,  static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1326                                struct ccs_env_acl_record *ptr,                                struct ccs_env_acl *ptr,
1327                                const struct ccs_condition *cond)                                const struct ccs_condition *cond)
1328  {  {
1329          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1014  static bool ccs_print_env_acl(struct ccs Line 1339  static bool ccs_print_env_acl(struct ccs
1339   * ccs_print_capability_acl - Print a capability ACL entry.   * ccs_print_capability_acl - Print a capability ACL entry.
1340   *   *
1341   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1342   * @ptr:  Pointer to "struct ccs_capability_acl_record".   * @ptr:  Pointer to "struct ccs_capability_acl".
1343   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1344   *   *
1345   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1346   */   */
1347  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1348                                       struct ccs_capability_acl_record *ptr,                                       struct ccs_capability_acl *ptr,
1349                                       const struct ccs_condition *cond)                                       const struct ccs_condition *cond)
1350  {  {
1351          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1037  static bool ccs_print_capability_acl(str Line 1362  static bool ccs_print_capability_acl(str
1362   * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.   * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1363   *   *
1364   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1365   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1366   *   *
1367   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1368   */   */
1369  static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,  static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1370                                   struct ccs_ip_network_acl_record *ptr)                                   struct ccs_ip_network_acl *ptr)
1371  {  {
1372          const u32 min_address = ptr->address.ipv4.min;          const u32 min_address = ptr->address.ipv4.min;
1373          const u32 max_address = ptr->address.ipv4.max;          const u32 max_address = ptr->address.ipv4.max;
# Line 1058  static bool ccs_print_ipv4_entry(struct Line 1383  static bool ccs_print_ipv4_entry(struct
1383   * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.   * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1384   *   *
1385   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1386   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1387   *   *
1388   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1389   */   */
1390  static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,  static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1391                                   struct ccs_ip_network_acl_record *ptr)                                   struct ccs_ip_network_acl *ptr)
1392  {  {
1393          char buf[64];          char buf[64];
1394          const struct in6_addr *min_address = ptr->address.ipv6.min;          const struct in6_addr *min_address = ptr->address.ipv6.min;
# Line 1083  static bool ccs_print_ipv6_entry(struct Line 1408  static bool ccs_print_ipv6_entry(struct
1408   * ccs_print_network_acl - Print a network ACL entry.   * ccs_print_network_acl - Print a network ACL entry.
1409   *   *
1410   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1411   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1412   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1413   *   *
1414   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1415   */   */
1416  static bool ccs_print_network_acl(struct ccs_io_buffer *head,  static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1417                                    struct ccs_ip_network_acl_record *ptr,                                    struct ccs_ip_network_acl *ptr,
1418                                    const struct ccs_condition *cond)                                    const struct ccs_condition *cond)
1419  {  {
1420          const int pos = head->read_avail;          int pos;
1421          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",          u8 bit;
1422                             ccs_net2keyword(ptr->operation_type)))          const u16 perm = ptr->perm;
1423                  goto out;          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1424          switch (ptr->record_type) {                  if (!(perm & (1 << bit)))
1425          case CCS_IP_RECORD_TYPE_ADDRESS_GROUP:                          continue;
1426                  if (!ccs_io_printf(head, "@%s",                  pos = head->read_avail;
1427                                     ptr->address.group->group_name->name))                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",
1428                          goto out;                                     ccs_net2keyword(bit)))
                 break;  
         case CCS_IP_RECORD_TYPE_IPv4:  
                 if (!ccs_print_ipv4_entry(head, ptr))  
1429                          goto out;                          goto out;
1430                  break;                  switch (ptr->address_type) {
1431          case CCS_IP_RECORD_TYPE_IPv6:                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1432                  if (!ccs_print_ipv6_entry(head, ptr))                          if (!ccs_io_printf(head, "@%s", ptr->address.group->
1433                                               group_name->name))
1434                                    goto out;
1435                            break;
1436                    case CCS_IP_ADDRESS_TYPE_IPv4:
1437                            if (!ccs_print_ipv4_entry(head, ptr))
1438                                    goto out;
1439                            break;
1440                    case CCS_IP_ADDRESS_TYPE_IPv6:
1441                            if (!ccs_print_ipv6_entry(head, ptr))
1442                                    goto out;
1443                            break;
1444                    }
1445                    if (!ccs_print_number_union(head, &ptr->port) ||
1446                        !ccs_print_condition(head, cond))
1447                          goto out;                          goto out;
                 break;  
1448          }          }
1449          if (!ccs_print_number_union(head, &ptr->port) ||          head->read_bit = 0;
             !ccs_print_condition(head, cond))  
                 goto out;  
1450          return true;          return true;
1451   out:   out:
1452            head->read_bit = bit;
1453          head->read_avail = pos;          head->read_avail = pos;
1454          return false;          return false;
1455  }  }
# Line 1124  static bool ccs_print_network_acl(struct Line 1458  static bool ccs_print_network_acl(struct
1458   * ccs_print_signal_acl - Print a signal ACL entry.   * ccs_print_signal_acl - Print a signal ACL entry.
1459   *   *
1460   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1461   * @ptr:  Pointer to "struct signale_acl_record".   * @ptr:  Pointer to "struct signale_acl".
1462   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1463   *   *
1464   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1465   */   */
1466  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1467                                   struct ccs_signal_acl_record *ptr,                                   struct ccs_signal_acl *ptr,
1468                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1469  {  {
1470          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1164  static bool ccs_print_execute_handler_re Line 1498  static bool ccs_print_execute_handler_re
1498   * ccs_print_mount_acl - Print a mount ACL entry.   * ccs_print_mount_acl - Print a mount ACL entry.
1499   *   *
1500   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1501   * @ptr:  Pointer to "struct ccs_mount_acl_record".   * @ptr:  Pointer to "struct ccs_mount_acl".
1502   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1503   *   *
1504   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1505   */   */
1506  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1507                                  struct ccs_mount_acl_record *ptr,                                  struct ccs_mount_acl *ptr,
1508                                  const struct ccs_condition *cond)                                  const struct ccs_condition *cond)
1509  {  {
1510          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1190  static bool ccs_print_mount_acl(struct c Line 1524  static bool ccs_print_mount_acl(struct c
1524   * ccs_print_umount_acl - Print a mount ACL entry.   * ccs_print_umount_acl - Print a mount ACL entry.
1525   *   *
1526   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1527   * @ptr:  Pointer to "struct ccs_umount_acl_record".   * @ptr:  Pointer to "struct ccs_umount_acl".
1528   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1529   *   *
1530   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1531   */   */
1532  static bool ccs_print_umount_acl(struct ccs_io_buffer *head,  static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
1533                                   struct ccs_umount_acl_record *ptr,                                   struct ccs_umount_acl *ptr,
1534                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1535  {  {
1536          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1213  static bool ccs_print_umount_acl(struct Line 1547  static bool ccs_print_umount_acl(struct
1547   * ccs_print_chroot_acl - Print a chroot ACL entry.   * ccs_print_chroot_acl - Print a chroot ACL entry.
1548   *   *
1549   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1550   * @ptr:  Pointer to "struct ccs_chroot_acl_record".   * @ptr:  Pointer to "struct ccs_chroot_acl".
1551   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1552   *   *
1553   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1554   */   */
1555  static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,  static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
1556                                   struct ccs_chroot_acl_record *ptr,                                   struct ccs_chroot_acl *ptr,
1557                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1558  {  {
1559          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1236  static bool ccs_print_chroot_acl(struct Line 1570  static bool ccs_print_chroot_acl(struct
1570   * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.   * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
1571   *   *
1572   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1573   * @ptr:  Pointer to "struct ccs_pivot_root_acl_record".   * @ptr:  Pointer to "struct ccs_pivot_root_acl".
1574   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1575   *   *
1576   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1577   */   */
1578  static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,  static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
1579                                       struct ccs_pivot_root_acl_record *ptr,                                       struct ccs_pivot_root_acl *ptr,
1580                                       const struct ccs_condition *cond)                                       const struct ccs_condition *cond)
1581  {  {
1582          const int pos = head->read_avail;          const int pos = head->read_avail;
# Line 1271  static bool ccs_print_entry(struct ccs_i Line 1605  static bool ccs_print_entry(struct ccs_i
1605          const u8 acl_type = ptr->type;          const u8 acl_type = ptr->type;
1606          if (ptr->is_deleted)          if (ptr->is_deleted)
1607                  return true;                  return true;
1608          if (acl_type == CCS_TYPE_SINGLE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH_ACL) {
1609                  struct ccs_single_path_acl_record *acl                  struct ccs_path_acl *acl
1610                          = container_of(ptr, struct ccs_single_path_acl_record,                          = container_of(ptr, struct ccs_path_acl,
1611                                         head);                                         head);
1612                  return ccs_print_single_path_acl(head, acl, cond);                  return ccs_print_path_acl(head, acl, cond);
1613          }          }
1614          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1615                  struct ccs_execute_handler_record *acl                  struct ccs_execute_handler_record *acl
# Line 1293  static bool ccs_print_entry(struct ccs_i Line 1627  static bool ccs_print_entry(struct ccs_i
1627          }          }
1628          if (head->read_execute_only)          if (head->read_execute_only)
1629                  return true;                  return true;
1630          if (acl_type == CCS_TYPE_MKDEV_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER3_ACL) {
1631                  struct ccs_mkdev_acl_record *acl                  struct ccs_path_number3_acl *acl
1632                          = container_of(ptr, struct ccs_mkdev_acl_record, head);                          = container_of(ptr, struct ccs_path_number3_acl, head);
1633                  return ccs_print_mkdev_acl(head, acl, cond);                  return ccs_print_path_number3_acl(head, acl, cond);
1634          }          }
1635          if (acl_type == CCS_TYPE_DOUBLE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH2_ACL) {
1636                  struct ccs_double_path_acl_record *acl                  struct ccs_path2_acl *acl
1637                          = container_of(ptr, struct ccs_double_path_acl_record,                          = container_of(ptr, struct ccs_path2_acl,
1638                                         head);                                         head);
1639                  return ccs_print_double_path_acl(head, acl, cond);                  return ccs_print_path2_acl(head, acl, cond);
1640          }          }
1641          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1642                  struct ccs_path_number_acl_record *acl                  struct ccs_path_number_acl *acl
1643                          = container_of(ptr, struct ccs_path_number_acl_record,                          = container_of(ptr, struct ccs_path_number_acl,
1644                                         head);                                         head);
1645                  return ccs_print_path_number_acl(head, acl, cond);                  return ccs_print_path_number_acl(head, acl, cond);
1646          }          }
1647          if (acl_type == CCS_TYPE_ENV_ACL) {          if (acl_type == CCS_TYPE_ENV_ACL) {
1648                  struct ccs_env_acl_record *acl                  struct ccs_env_acl *acl
1649                          = container_of(ptr, struct ccs_env_acl_record, head);                          = container_of(ptr, struct ccs_env_acl, head);
1650                  return ccs_print_env_acl(head, acl, cond);                  return ccs_print_env_acl(head, acl, cond);
1651          }          }
1652          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1653                  struct ccs_capability_acl_record *acl                  struct ccs_capability_acl *acl
1654                          = container_of(ptr, struct ccs_capability_acl_record,                          = container_of(ptr, struct ccs_capability_acl,
1655                                         head);                                         head);
1656                  return ccs_print_capability_acl(head, acl, cond);                  return ccs_print_capability_acl(head, acl, cond);
1657          }          }
1658          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1659                  struct ccs_ip_network_acl_record *acl                  struct ccs_ip_network_acl *acl
1660                          = container_of(ptr, struct ccs_ip_network_acl_record,                          = container_of(ptr, struct ccs_ip_network_acl,
1661                                         head);                                         head);
1662                  return ccs_print_network_acl(head, acl, cond);                  return ccs_print_network_acl(head, acl, cond);
1663          }          }
1664          if (acl_type == CCS_TYPE_SIGNAL_ACL) {          if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1665                  struct ccs_signal_acl_record *acl                  struct ccs_signal_acl *acl
1666                          = container_of(ptr, struct ccs_signal_acl_record, head);                          = container_of(ptr, struct ccs_signal_acl, head);
1667                  return ccs_print_signal_acl(head, acl, cond);                  return ccs_print_signal_acl(head, acl, cond);
1668          }          }
1669          if (acl_type == CCS_TYPE_MOUNT_ACL) {          if (acl_type == CCS_TYPE_MOUNT_ACL) {
1670                  struct ccs_mount_acl_record *acl                  struct ccs_mount_acl *acl
1671                          = container_of(ptr, struct ccs_mount_acl_record, head);                          = container_of(ptr, struct ccs_mount_acl, head);
1672                  return ccs_print_mount_acl(head, acl, cond);                  return ccs_print_mount_acl(head, acl, cond);
1673          }          }
1674          if (acl_type == CCS_TYPE_UMOUNT_ACL) {          if (acl_type == CCS_TYPE_UMOUNT_ACL) {
1675                  struct ccs_umount_acl_record *acl                  struct ccs_umount_acl *acl
1676                          = container_of(ptr, struct ccs_umount_acl_record, head);                          = container_of(ptr, struct ccs_umount_acl, head);
1677                  return ccs_print_umount_acl(head, acl, cond);                  return ccs_print_umount_acl(head, acl, cond);
1678          }          }
1679          if (acl_type == CCS_TYPE_CHROOT_ACL) {          if (acl_type == CCS_TYPE_CHROOT_ACL) {
1680                  struct ccs_chroot_acl_record *acl                  struct ccs_chroot_acl *acl
1681                          = container_of(ptr, struct ccs_chroot_acl_record, head);                          = container_of(ptr, struct ccs_chroot_acl, head);
1682                  return ccs_print_chroot_acl(head, acl, cond);                  return ccs_print_chroot_acl(head, acl, cond);
1683          }          }
1684          if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {          if (acl_type == CCS_TYPE_PIVOT_ROOT_ACL) {
1685                  struct ccs_pivot_root_acl_record *acl                  struct ccs_pivot_root_acl *acl
1686                          = container_of(ptr, struct ccs_pivot_root_acl_record,                          = container_of(ptr, struct ccs_pivot_root_acl,
1687                                         head);                                         head);
1688                  return ccs_print_pivot_root_acl(head, acl, cond);                  return ccs_print_pivot_root_acl(head, acl, cond);
1689          }          }
# Line 1362  static bool ccs_print_entry(struct ccs_i Line 1696  static bool ccs_print_entry(struct ccs_i
1696   *   *
1697   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1698   *   *
  * Returns 0.  
  *  
1699   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1700   */   */
1701  static int ccs_read_domain_policy(struct ccs_io_buffer *head)  static void ccs_read_domain_policy(struct ccs_io_buffer *head)
1702  {  {
1703          struct list_head *dpos;          struct list_head *dpos;
1704          struct list_head *apos;          struct list_head *apos;
         ccs_check_read_lock();  
1705          if (head->read_eof)          if (head->read_eof)
1706                  return 0;                  return;
1707          if (head->read_step == 0)          if (head->read_step == 0)
1708                  head->read_step = 1;                  head->read_step = 1;
1709          list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {          list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
# Line 1403  static int ccs_read_domain_policy(struct Line 1734  static int ccs_read_domain_policy(struct
1734                                     transition_failed,                                     transition_failed,
1735                                     ignore_global_allow_read,                                     ignore_global_allow_read,
1736                                     ignore_global_allow_env))                                     ignore_global_allow_env))
1737                          return 0;                          return;
1738                  head->read_step = 2;                  head->read_step = 2;
1739   acl_loop:   acl_loop:
1740                  if (head->read_step == 3)                  if (head->read_step == 3)
# Line 1414  static int ccs_read_domain_policy(struct Line 1745  static int ccs_read_domain_policy(struct
1745                          struct ccs_acl_info *ptr                          struct ccs_acl_info *ptr
1746                                  = list_entry(apos, struct ccs_acl_info, list);                                  = list_entry(apos, struct ccs_acl_info, list);
1747                          if (!ccs_print_entry(head, ptr))                          if (!ccs_print_entry(head, ptr))
1748                                  return 0;                                  return;
1749                  }                  }
1750                  head->read_step = 3;                  head->read_step = 3;
1751   tail_mark:   tail_mark:
1752                  if (!ccs_io_printf(head, "\n"))                  if (!ccs_io_printf(head, "\n"))
1753                          return 0;                          return;
1754                  head->read_step = 1;                  head->read_step = 1;
1755                  if (head->read_single_domain)                  if (head->read_single_domain)
1756                          break;                          break;
1757          }          }
1758          head->read_eof = true;          head->read_eof = true;
         return 0;  
1759  }  }
1760    
1761  /**  /**
# Line 1438  static int ccs_read_domain_policy(struct Line 1768  static int ccs_read_domain_policy(struct
1768   * This is equivalent to doing   * This is equivalent to doing
1769   *   *
1770   *     ( echo "select " $domainname; echo "use_profile " $profile ) |   *     ( echo "select " $domainname; echo "use_profile " $profile ) |
1771   *     /usr/lib/ccs/loadpolicy -d   *     /usr/sbin/ccs-loadpolicy -d
1772   *   *
1773   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1774   */   */
# Line 1448  static int ccs_write_domain_profile(stru Line 1778  static int ccs_write_domain_profile(stru
1778          char *cp = strchr(data, ' ');          char *cp = strchr(data, ' ');
1779          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
1780          unsigned int profile;          unsigned int profile;
         ccs_check_read_lock();  
1781          if (!cp)          if (!cp)
1782                  return -EINVAL;                  return -EINVAL;
1783          *cp = '\0';          *cp = '\0';
# Line 1456  static int ccs_write_domain_profile(stru Line 1785  static int ccs_write_domain_profile(stru
1785          if (profile >= CCS_MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
1786                  return -EINVAL;                  return -EINVAL;
1787          domain = ccs_find_domain(cp + 1);          domain = ccs_find_domain(cp + 1);
1788          if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))          if (domain && ccs_profile(profile))
1789                  domain->profile = (u8) profile;                  domain->profile = (u8) profile;
1790          return 0;          return 0;
1791  }  }
# Line 1466  static int ccs_write_domain_profile(stru Line 1795  static int ccs_write_domain_profile(stru
1795   *   *
1796   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1797   *   *
  * Returns list of profile number and domainname pairs.  
  *  
1798   * This is equivalent to doing   * This is equivalent to doing
1799   *   *
1800   *     grep -A 1 '^<kernel>' /proc/ccs/domain_policy |   *     grep -A 1 '^<kernel>' /proc/ccs/domain_policy |
# Line 1477  static int ccs_write_domain_profile(stru Line 1804  static int ccs_write_domain_profile(stru
1804   *   *
1805   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1806   */   */
1807  static int ccs_read_domain_profile(struct ccs_io_buffer *head)  static void ccs_read_domain_profile(struct ccs_io_buffer *head)
1808  {  {
1809          struct list_head *pos;          struct list_head *pos;
         ccs_check_read_lock();  
1810          if (head->read_eof)          if (head->read_eof)
1811                  return 0;                  return;
1812          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1813                  struct ccs_domain_info *domain;                  struct ccs_domain_info *domain;
1814                  domain = list_entry(pos, struct ccs_domain_info, list);                  domain = list_entry(pos, struct ccs_domain_info, list);
# Line 1490  static int ccs_read_domain_profile(struc Line 1816  static int ccs_read_domain_profile(struc
1816                          continue;                          continue;
1817                  if (!ccs_io_printf(head, "%u %s\n", domain->profile,                  if (!ccs_io_printf(head, "%u %s\n", domain->profile,
1818                                     domain->domainname->name))                                     domain->domainname->name))
1819                          return 0;                          return;
1820          }          }
1821          head->read_eof = true;          head->read_eof = true;
         return 0;  
1822  }  }
1823    
1824  /**  /**
# Line 1520  static int ccs_write_pid(struct ccs_io_b Line 1845  static int ccs_write_pid(struct ccs_io_b
1845   *   *
1846   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1847   */   */
1848  static int ccs_read_pid(struct ccs_io_buffer *head)  static void ccs_read_pid(struct ccs_io_buffer *head)
1849  {  {
1850          char *buf = head->write_buf;          char *buf = head->write_buf;
1851          bool task_info = false;          bool task_info = false;
1852            bool global_pid = false;
1853          unsigned int pid;          unsigned int pid;
1854          struct task_struct *p;          struct task_struct *p;
1855          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1856          u32 ccs_flags = 0;          u32 ccs_flags = 0;
         ccs_check_read_lock();  
1857          /* Accessing write_buf is safe because head->io_sem is held. */          /* Accessing write_buf is safe because head->io_sem is held. */
1858          if (!buf)          if (!buf)
1859                  goto done; /* Do nothing if open(O_RDONLY). */                  return; /* Do nothing if open(O_RDONLY). */
1860          if (head->read_avail || head->read_eof)          if (head->read_avail || head->read_eof)
1861                  goto done;                  return;
1862          head->read_eof = true;          head->read_eof = true;
1863          if (ccs_str_starts(&buf, "info "))          if (ccs_str_starts(&buf, "info "))
1864                  task_info = true;                  task_info = true;
1865            if (ccs_str_starts(&buf, "global-pid "))
1866                    global_pid = true;
1867          pid = (unsigned int) simple_strtoul(buf, NULL, 10);          pid = (unsigned int) simple_strtoul(buf, NULL, 10);
         /***** CRITICAL SECTION START *****/  
1868          read_lock(&tasklist_lock);          read_lock(&tasklist_lock);
1869    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1870            if (global_pid)
1871                    p = find_task_by_pid_ns(pid, &init_pid_ns);
1872            else
1873                    p = find_task_by_vpid(pid);
1874    #else
1875          p = find_task_by_pid(pid);          p = find_task_by_pid(pid);
1876    #endif
1877          if (p) {          if (p) {
1878                  domain = ccs_task_domain(p);                  domain = ccs_task_domain(p);
1879                  ccs_flags = p->ccs_flags;                  ccs_flags = p->ccs_flags;
1880          }          }
1881          read_unlock(&tasklist_lock);          read_unlock(&tasklist_lock);
         /***** CRITICAL SECTION END *****/  
1882          if (!domain)          if (!domain)
1883                  goto done;                  return;
1884          if (!task_info)          if (!task_info)
1885                  ccs_io_printf(head, "%u %u %s", pid, domain->profile,                  ccs_io_printf(head, "%u %u %s", pid, domain->profile,
1886                                domain->domainname->name);                                domain->domainname->name);
1887          else          else
1888                  ccs_io_printf(head, "%u manager=%s execute_handler=%s "                  ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1889                                "state[0]=%u state[1]=%u state[2]=%u", pid,                                "state[0]=%u state[1]=%u state[2]=%u", pid,
1890                                ccs_flags & CCS_TASK_IS_POLICY_MANAGER ?                                ccs_yesno(ccs_flags &
1891                                "yes" : "no",                                          CCS_TASK_IS_POLICY_MANAGER),
1892                                ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ?                                ccs_yesno(ccs_flags &
1893                                "yes" : "no",                                          CCS_TASK_IS_EXECUTE_HANDLER),
1894                                (u8) (ccs_flags >> 24),                                (u8) (ccs_flags >> 24),
1895                                (u8) (ccs_flags >> 16),                                (u8) (ccs_flags >> 16),
1896                                (u8) (ccs_flags >> 8));                                (u8) (ccs_flags >> 8));
  done:  
         return 0;  
1897  }  }
1898    
1899  /**  /**
# Line 1613  static int ccs_write_exception_policy(st Line 1943  static int ccs_write_exception_policy(st
1943   *   *
1944   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1945   *   *
  * Returns 0 on success, -EINVAL otherwise.  
  *  
1946   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1947   */   */
1948  static int ccs_read_exception_policy(struct ccs_io_buffer *head)  static void ccs_read_exception_policy(struct ccs_io_buffer *head)
1949  {  {
1950          ccs_check_read_lock();          if (head->read_eof)
1951          if (!head->read_eof) {                  return;
1952                  switch (head->read_step) {          switch (head->read_step) {
1953                  case 0:          case 0:
1954                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1955                          head->read_step = 1;                  head->read_step = 1;
1956                  case 1:          case 1:
1957                          if (!ccs_read_domain_keeper_policy(head))                  if (!ccs_read_domain_keeper_policy(head))
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 2;  
                 case 2:  
                         if (!ccs_read_globally_readable_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 3;  
                 case 3:  
                         if (!ccs_read_globally_usable_env_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 4;  
                 case 4:  
                         if (!ccs_read_domain_initializer_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 6;  
                 case 6:  
                         if (!ccs_read_aggregator_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 7;  
                 case 7:  
                         if (!ccs_read_file_pattern(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 8;  
                 case 8:  
                         if (!ccs_read_no_rewrite_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 9;  
                 case 9:  
                         if (!ccs_read_path_group_policy(head))  
                                 break;  
                         head->read_var1 = NULL;  
                         head->read_var2 = NULL;  
                         head->read_step = 10;  
                 case 10:  
                         if (!ccs_read_number_group_policy(head))  
                                 break;  
                         head->read_var1 = NULL;  
                         head->read_var2 = NULL;  
                         head->read_step = 11;  
                 case 11:  
                         if (!ccs_read_address_group_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 12;  
                 case 12:  
                         if (!ccs_read_reserved_port_policy(head))  
                                 break;  
                         head->read_eof = true;  
1958                          break;                          break;
1959                  default:                  head->read_var2 = NULL;
1960                          return -EINVAL;                  head->read_step = 2;
1961                  }          case 2:
1962                    if (!ccs_read_globally_readable_policy(head))
1963                            break;
1964                    head->read_var2 = NULL;
1965                    head->read_step = 3;
1966            case 3:
1967                    if (!ccs_read_globally_usable_env_policy(head))
1968                            break;
1969                    head->read_var2 = NULL;
1970                    head->read_step = 4;
1971            case 4:
1972                    if (!ccs_read_domain_initializer_policy(head))
1973                            break;
1974                    head->read_var2 = NULL;
1975                    head->read_step = 6;
1976            case 6:
1977                    if (!ccs_read_aggregator_policy(head))
1978                            break;
1979                    head->read_var2 = NULL;
1980                    head->read_step = 7;
1981            case 7:
1982                    if (!ccs_read_file_pattern(head))
1983                            break;
1984                    head->read_var2 = NULL;
1985                    head->read_step = 8;
1986            case 8:
1987                    if (!ccs_read_no_rewrite_policy(head))
1988                            break;
1989                    head->read_var2 = NULL;
1990                    head->read_step = 9;
1991            case 9:
1992                    if (!ccs_read_path_group_policy(head))
1993                            break;
1994                    head->read_var1 = NULL;
1995                    head->read_var2 = NULL;
1996                    head->read_step = 10;
1997            case 10:
1998                    if (!ccs_read_number_group_policy(head))
1999                            break;
2000                    head->read_var1 = NULL;
2001                    head->read_var2 = NULL;
2002                    head->read_step = 11;
2003            case 11:
2004                    if (!ccs_read_address_group_policy(head))
2005                            break;
2006                    head->read_var2 = NULL;
2007                    head->read_step = 12;
2008            case 12:
2009                    if (!ccs_read_reserved_port_policy(head))
2010                            break;
2011                    head->read_eof = true;
2012          }          }
         return 0;  
2013  }  }
2014    
2015  /**  /**
# Line 1714  static bool ccs_get_argv0(struct ccs_exe Line 2037  static bool ccs_get_argv0(struct ccs_exe
2037                  while (offset < PAGE_SIZE) {                  while (offset < PAGE_SIZE) {
2038                          const char *kaddr = ee->dump.data;                          const char *kaddr = ee->dump.data;
2039                          const unsigned char c = kaddr[offset++];                          const unsigned char c = kaddr[offset++];
2040                          if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {                          if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
2041                                  if (c == '\\') {                                  if (c == '\\') {
2042                                          arg_ptr[arg_len++] = '\\';                                          arg_ptr[arg_len++] = '\\';
2043                                          arg_ptr[arg_len++] = '\\';                                          arg_ptr[arg_len++] = '\\';
                                 } else if (c == '/') {  
                                         arg_len = 0;  
2044                                  } else if (c > ' ' && c < 127) {                                  } else if (c > ' ' && c < 127) {
2045                                          arg_ptr[arg_len++] = c;                                          arg_ptr[arg_len++] = c;
2046                                  } else {                                  } else {
# Line 1744  static bool ccs_get_argv0(struct ccs_exe Line 2065  static bool ccs_get_argv0(struct ccs_exe
2065          return false;          return false;
2066  }  }
2067    
2068    /**
2069     * ccs_get_execute_condition - Get condition part for execute requests.
2070     *
2071     * @ee: Pointer to "struct ccs_execve_entry".
2072     *
2073     * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
2074     */
2075  static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry  static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry
2076                                                         *ee)                                                         *ee)
2077  {  {
# Line 1752  static struct ccs_condition *ccs_get_exe Line 2080  static struct ccs_condition *ccs_get_exe
2080          int len = 256;          int len = 256;
2081          char *realpath = NULL;          char *realpath = NULL;
2082          char *argv0 = NULL;          char *argv0 = NULL;
2083          if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) {          const struct ccs_profile *profile = ccs_profile(ee->r.domain->profile);
2084            if (profile->learning->learning_exec_realpath) {
2085                  struct file *file = ee->bprm->file;                  struct file *file = ee->bprm->file;
2086  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2087                  struct path path = { file->f_vfsmnt, file->f_dentry };                  struct path path = { file->f_vfsmnt, file->f_dentry };
# Line 1763  static struct ccs_condition *ccs_get_exe Line 2092  static struct ccs_condition *ccs_get_exe
2092                  if (realpath)                  if (realpath)
2093                          len += strlen(realpath) + 17;                          len += strlen(realpath) + 17;
2094          }          }
2095          if (ccs_check_flags(NULL, CCS_AUTOLEARN_EXEC_REALPATH)) {          if (profile->learning->learning_exec_argv0) {
2096                  if (ccs_get_argv0(ee)) {                  if (ccs_get_argv0(ee)) {
2097                          argv0 = ee->tmp;                          argv0 = ee->tmp;
2098                          len += strlen(argv0) + 16;                          len += strlen(argv0) + 16;
2099                  }                  }
2100          }          }
2101          buf = kmalloc(len, GFP_KERNEL);          buf = kmalloc(len, GFP_KERNEL);
2102          if (!buf)          if (!buf) {
2103                    kfree(realpath);
2104                  return NULL;                  return NULL;
2105            }
2106          snprintf(buf, len - 1, "if");          snprintf(buf, len - 1, "if");
2107          if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {          if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
2108                  const int pos = strlen(buf);                  const int pos = strlen(buf);
# Line 1794  static struct ccs_condition *ccs_get_exe Line 2125  static struct ccs_condition *ccs_get_exe
2125          return cond;          return cond;
2126  }  }
2127    
2128    /**
2129     * ccs_get_symlink_condition - Get condition part for symlink requests.
2130     *
2131     * @r: Pointer to "struct ccs_request_info".
2132     *
2133     * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
2134     */
2135    static struct ccs_condition *ccs_get_symlink_condition(struct ccs_request_info
2136                                                           *r)
2137    {
2138            struct ccs_condition *cond;
2139            char *buf;
2140            int len = 256;
2141            const char *symlink = NULL;
2142            const struct ccs_profile *profile = ccs_profile(r->profile);
2143            if (profile->learning->learning_symlink_target) {
2144                    symlink = r->obj->symlink_target->name;
2145                    len += strlen(symlink) + 18;
2146            }
2147            buf = kmalloc(len, GFP_KERNEL);
2148            if (!buf)
2149                    return NULL;
2150            snprintf(buf, len - 1, "if");
2151            if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
2152                    const int pos = strlen(buf);
2153                    snprintf(buf + pos, len - pos - 1,
2154                             " task.type=execute_handler");
2155            }
2156            if (symlink) {
2157                    const int pos = strlen(buf);
2158                    snprintf(buf + pos, len - pos - 1, " symlink.target=\"%s\"",
2159                             symlink);
2160            }
2161            cond = ccs_get_condition(buf);
2162            kfree(buf);
2163            return cond;
2164    }
2165    
2166  /* Wait queue for ccs_query_list. */  /* Wait queue for ccs_query_list. */
2167  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
2168    
# Line 1817  static LIST_HEAD(ccs_query_list); Line 2186  static LIST_HEAD(ccs_query_list);
2186  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
2187    
2188  /**  /**
2189   * ccs_check_supervisor - Ask for the supervisor's decision.   * ccs_supervisor - Ask for the supervisor's decision.
2190   *   *
2191   * @r:       Pointer to "struct ccs_request_info".   * @r:       Pointer to "struct ccs_request_info".
2192   * @fmt:     The printf()'s format string, followed by parameters.   * @fmt:     The printf()'s format string, followed by parameters.
# Line 1827  static atomic_t ccs_query_observers = AT Line 2196  static atomic_t ccs_query_observers = AT
2196   * retry the access request which violated the policy in enforcing mode,   * retry the access request which violated the policy in enforcing mode,
2197   * 0 if it is not in enforcing mode, -EPERM otherwise.   * 0 if it is not in enforcing mode, -EPERM otherwise.
2198   */   */
2199  int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
2200  {  {
2201          va_list args;          va_list args;
2202          int error = -EPERM;          int error = -EPERM;
# Line 1842  int ccs_check_supervisor(struct ccs_requ Line 2211  int ccs_check_supervisor(struct ccs_requ
2211          switch (r->mode) {          switch (r->mode) {
2212                  char *buffer;                  char *buffer;
2213                  struct ccs_condition *cond;                  struct ccs_condition *cond;
2214          case 1:          case CCS_CONFIG_LEARNING:
2215                  if (!ccs_domain_quota_ok(r))                  if (!ccs_domain_quota_ok(r))
2216                          return 0;                          return 0;
2217                  va_start(args, fmt);                  va_start(args, fmt);
# Line 1857  int ccs_check_supervisor(struct ccs_requ Line 2226  int ccs_check_supervisor(struct ccs_requ
2226                  ccs_normalize_line(buffer);                  ccs_normalize_line(buffer);
2227                  if (r->ee && !strncmp(buffer, "allow_execute ", 14))                  if (r->ee && !strncmp(buffer, "allow_execute ", 14))
2228                          cond = ccs_get_execute_condition(r->ee);                          cond = ccs_get_execute_condition(r->ee);
2229                    else if (r->obj && r->obj->symlink_target)
2230                            cond = ccs_get_symlink_condition(r);
2231                  else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {                  else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
2232                          char str[] = "if task.type=execute_handler";                          char str[] = "if task.type=execute_handler";
2233                          cond = ccs_get_condition(str);                          cond = ccs_get_condition(str);
# Line 1866  int ccs_check_supervisor(struct ccs_requ Line 2237  int ccs_check_supervisor(struct ccs_requ
2237                  ccs_put_condition(cond);                  ccs_put_condition(cond);
2238                  kfree(buffer);                  kfree(buffer);
2239                  /* fall through */                  /* fall through */
2240          case 2:          case CCS_CONFIG_PERMISSIVE:
2241                  return 0;                  return 0;
2242          }          }
2243          if (!atomic_read(&ccs_query_observers)) {          if (!atomic_read(&ccs_query_observers)) {
2244                  int i;                  int i;
2245                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
2246                          return -EPERM;                          return -EPERM;
2247                  for (i = 0; i < ccs_check_flags(r->domain, CCS_SLEEP_PERIOD);                  for (i = 0; i < ccs_profile(r->domain->profile)->enforcing->
2248                       i++) {                               enforcing_penalty; i++) {
2249                          set_current_state(TASK_INTERRUPTIBLE);                          set_current_state(TASK_INTERRUPTIBLE);
2250                          schedule_timeout(HZ / 10);                          schedule_timeout(HZ / 10);
2251                  }                  }
# Line 1894  int ccs_check_supervisor(struct ccs_requ Line 2265  int ccs_check_supervisor(struct ccs_requ
2265          if (!ccs_query_entry->query)          if (!ccs_query_entry->query)
2266                  goto out;                  goto out;
2267          INIT_LIST_HEAD(&ccs_query_entry->list);          INIT_LIST_HEAD(&ccs_query_entry->list);
         /***** CRITICAL SECTION START *****/  
2268          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2269          if (ccs_quota_for_query && ccs_query_memory_size + len +          if (ccs_quota_for_query && ccs_query_memory_size + len +
2270              sizeof(*ccs_query_entry) >= ccs_quota_for_query) {              sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
# Line 1904  int ccs_check_supervisor(struct ccs_requ Line 2274  int ccs_check_supervisor(struct ccs_requ
2274                  ccs_query_entry->serial = ccs_serial++;                  ccs_query_entry->serial = ccs_serial++;
2275          }          }
2276          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2277          if (quota_exceeded)          if (quota_exceeded)
2278                  goto out;                  goto out;
2279          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",
# Line 1915  int ccs_check_supervisor(struct ccs_requ Line 2284  int ccs_check_supervisor(struct ccs_requ
2284          vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);          vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
2285          ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;          ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
2286          va_end(args);          va_end(args);
         /***** CRITICAL SECTION START *****/  
2287          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2288          list_add_tail(&ccs_query_entry->list, &ccs_query_list);          list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2289          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2290          /* Give 10 seconds for supervisor's opinion. */          /* Give 10 seconds for supervisor's opinion. */
2291          for (ccs_query_entry->timer = 0;          for (ccs_query_entry->timer = 0;
2292               atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;               atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;
# Line 1930  int ccs_check_supervisor(struct ccs_requ Line 2297  int ccs_check_supervisor(struct ccs_requ
2297                  if (ccs_query_entry->answer)                  if (ccs_query_entry->answer)
2298                          break;                          break;
2299          }          }
         /***** CRITICAL SECTION START *****/  
2300          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2301          list_del(&ccs_query_entry->list);          list_del(&ccs_query_entry->list);
2302          ccs_query_memory_size -= len + sizeof(*ccs_query_entry);          ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
2303          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2304          switch (ccs_query_entry->answer) {          switch (ccs_query_entry->answer) {
2305          case 3: /* Asked to retry by administrator. */          case 3: /* Asked to retry by administrator. */
2306                  error = 1;                  error = 1;
# Line 1976  static int ccs_poll_query(struct file *f Line 2341  static int ccs_poll_query(struct file *f
2341          bool found = false;          bool found = false;
2342          u8 i;          u8 i;
2343          for (i = 0; i < 2; i++) {          for (i = 0; i < 2; i++) {
                 /***** CRITICAL SECTION START *****/  
2344                  spin_lock(&ccs_query_list_lock);                  spin_lock(&ccs_query_list_lock);
2345                  list_for_each(tmp, &ccs_query_list) {                  list_for_each(tmp, &ccs_query_list) {
2346                          struct ccs_query_entry *ptr                          struct ccs_query_entry *ptr
# Line 1987  static int ccs_poll_query(struct file *f Line 2351  static int ccs_poll_query(struct file *f
2351                          break;                          break;
2352                  }                  }
2353                  spin_unlock(&ccs_query_list_lock);                  spin_unlock(&ccs_query_list_lock);
                 /***** CRITICAL SECTION END *****/  
2354                  if (found)                  if (found)
2355                          return POLLIN | POLLRDNORM;                          return POLLIN | POLLRDNORM;
2356                  if (i)                  if (i)
# Line 2001  static int ccs_poll_query(struct file *f Line 2364  static int ccs_poll_query(struct file *f
2364   * ccs_read_query - Read access requests which violated policy in enforcing mode.   * ccs_read_query - Read access requests which violated policy in enforcing mode.
2365   *   *
2366   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns 0.  
2367   */   */
2368  static int ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2369  {  {
2370          struct list_head *tmp;          struct list_head *tmp;
2371          int pos = 0;          int pos = 0;
2372          int len = 0;          int len = 0;
2373          char *buf;          char *buf;
2374          if (head->read_avail)          if (head->read_avail)
2375                  return 0;                  return;
2376          if (head->read_buf) {          if (head->read_buf) {
2377                  kfree(head->read_buf);                  kfree(head->read_buf);
2378                  head->read_buf = NULL;                  head->read_buf = NULL;
2379                  head->readbuf_size = 0;                  head->readbuf_size = 0;
2380          }          }
         /***** CRITICAL SECTION START *****/  
2381          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2382          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2383                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 2030  static int ccs_read_query(struct ccs_io_ Line 2390  static int ccs_read_query(struct ccs_io_
2390                  break;                  break;
2391          }          }
2392          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2393          if (!len) {          if (!len) {
2394                  head->read_step = 0;                  head->read_step = 0;
2395                  return 0;                  return;
2396          }          }
2397          buf = kzalloc(len, GFP_KERNEL);          buf = kzalloc(len, GFP_KERNEL);
2398          if (!buf)          if (!buf)
2399                  return 0;                  return;
2400          pos = 0;          pos = 0;
         /***** CRITICAL SECTION START *****/  
2401          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2402          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2403                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 2057  static int ccs_read_query(struct ccs_io_ Line 2415  static int ccs_read_query(struct ccs_io_
2415                  break;                  break;
2416          }          }
2417          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2418          if (buf[0]) {          if (buf[0]) {
2419                  head->read_avail = len;                  head->read_avail = len;
2420                  head->readbuf_size = head->read_avail;                  head->readbuf_size = head->read_avail;
# Line 2066  static int ccs_read_query(struct ccs_io_ Line 2423  static int ccs_read_query(struct ccs_io_
2423          } else {          } else {
2424                  kfree(buf);                  kfree(buf);
2425          }          }
         return 0;  
2426  }  }
2427    
2428  /**  /**
# Line 2082  static int ccs_write_answer(struct ccs_i Line 2438  static int ccs_write_answer(struct ccs_i
2438          struct list_head *tmp;          struct list_head *tmp;
2439          unsigned int serial;          unsigned int serial;
2440          unsigned int answer;          unsigned int answer;
         /***** CRITICAL SECTION START *****/  
2441          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2442          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2443                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 2090  static int ccs_write_answer(struct ccs_i Line 2445  static int ccs_write_answer(struct ccs_i
2445                  ptr->timer = 0;                  ptr->timer = 0;
2446          }          }
2447          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2448          if (sscanf(data, "A%u=%u", &serial, &answer) != 2)          if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
2449                  return -EINVAL;                  return -EINVAL;
         /***** CRITICAL SECTION START *****/  
2450          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2451          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2452                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 2105  static int ccs_write_answer(struct ccs_i Line 2458  static int ccs_write_answer(struct ccs_i
2458                  break;                  break;
2459          }          }
2460          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2461          return 0;          return 0;
2462  }  }
2463    
# Line 2113  static int ccs_write_answer(struct ccs_i Line 2465  static int ccs_write_answer(struct ccs_i
2465   * ccs_read_version: Get version.   * ccs_read_version: Get version.
2466   *   *
2467   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns version information.  
2468   */   */
2469  static int ccs_read_version(struct ccs_io_buffer *head)  static void ccs_read_version(struct ccs_io_buffer *head)
2470  {  {
2471          if (!head->read_eof) {          if (head->read_eof)
2472                  ccs_io_printf(head, "1.7.0-pre");                  return;
2473                  head->read_eof = true;          ccs_io_printf(head, "1.7.0-rc");
2474          }          head->read_eof = true;
         return 0;  
2475  }  }
2476    
2477  /**  /**
2478   * ccs_read_self_domain - Get the current process's domainname.   * ccs_read_self_domain - Get the current process's domainname.
2479   *   *
2480   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns the current process's domainname.  
2481   */   */
2482  static int ccs_read_self_domain(struct ccs_io_buffer *head)  static void ccs_read_self_domain(struct ccs_io_buffer *head)
2483  {  {
2484          if (!head->read_eof) {          if (head->read_eof)
2485                  /*                  return;
2486                   * ccs_current_domain()->domainname != NULL          /*
2487                   * because every process belongs to a domain and           * ccs_current_domain()->domainname != NULL because every process
2488                   * the domain's name cannot be NULL.           * belongs to a domain and the domain's name cannot be NULL.
2489                   */           */
2490                  ccs_io_printf(head, "%s",          ccs_io_printf(head, "%s", ccs_current_domain()->domainname->name);
2491                                ccs_current_domain()->domainname->name);          head->read_eof = true;
                 head->read_eof = true;  
         }  
         return 0;  
2492  }  }
2493    
2494  /**  /**
# Line 2229  int ccs_open_control(const u8 type, stru Line 2573  int ccs_open_control(const u8 type, stru
2573                   */                   */
2574                  head->read = NULL;                  head->read = NULL;
2575                  head->poll = NULL;                  head->poll = NULL;
2576          } else if (type != CCS_QUERY &&          } else if (!head->poll) {
2577                     type != CCS_GRANTLOG && type != CCS_REJECTLOG) {                  /* Don't allocate read_buf for poll() access. */
                 /*  
                  * Don't allocate buffer for reading if the file is one of  
                  * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.  
                  */  
2578                  if (!head->readbuf_size)                  if (!head->readbuf_size)
2579                          head->readbuf_size = 4096 * 2;                          head->readbuf_size = 4096;
2580                  head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);                  head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
2581                  if (!head->read_buf) {                  if (!head->read_buf) {
2582                          kfree(head);                          kfree(head);
# Line 2250  int ccs_open_control(const u8 type, stru Line 2590  int ccs_open_control(const u8 type, stru
2590                   */                   */
2591                  head->write = NULL;                  head->write = NULL;
2592          } else if (head->write) {          } else if (head->write) {
2593                  head->writebuf_size = 4096 * 2;                  head->writebuf_size = 4096;
2594                  head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);                  head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
2595                  if (!head->write_buf) {                  if (!head->write_buf) {
2596                          kfree(head->read_buf);                          kfree(head->read_buf);
# Line 2271  int ccs_open_control(const u8 type, stru Line 2611  int ccs_open_control(const u8 type, stru
2611                  ccs_read_control(file, NULL, 0);                  ccs_read_control(file, NULL, 0);
2612          /*          /*
2613           * If the file is /proc/ccs/query , increment the observer counter.           * If the file is /proc/ccs/query , increment the observer counter.
2614           * The obserber counter is used by ccs_check_supervisor() to see if           * The obserber counter is used by ccs_supervisor() to see if
2615           * there is some process monitoring /proc/ccs/query.           * there is some process monitoring /proc/ccs/query.
2616           */           */
2617          else if (type == CCS_QUERY)          else if (type == CCS_QUERY)
# Line 2286  int ccs_open_control(const u8 type, stru Line 2626  int ccs_open_control(const u8 type, stru
2626   * @wait: Pointer to "poll_table".   * @wait: Pointer to "poll_table".
2627   *   *
2628   * Waits for read readiness.   * Waits for read readiness.
2629   * /proc/ccs/query is handled by /usr/lib/ccs/ccs-queryd and   * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and
2630   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
2631   * /usr/lib/ccs/ccs-auditd.   * /usr/sbin/ccs-auditd.
2632   */   */
2633  int ccs_poll_control(struct file *file, poll_table *wait)  int ccs_poll_control(struct file *file, poll_table *wait)
2634  {  {
# Line 2319  int ccs_read_control(struct file *file, Line 2659  int ccs_read_control(struct file *file,
2659                  return -EFAULT;                  return -EFAULT;
2660          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2661                  return -EINTR;                  return -EINTR;
2662          /* Call the policy handler. */          while (1) {
2663          len = head->read(head);                  /* Call the policy handler. */
2664          if (len < 0)                  head->read(head);
2665                  goto out;                  /* Write to buffer. */
2666          /* Write to buffer. */                  len = head->read_avail;
2667          len = head->read_avail;                  if (len || head->poll || head->read_eof)
2668                            break;
2669                    len = head->readbuf_size * 2;
2670                    cp = kzalloc(len, GFP_KERNEL);
2671                    if (!cp) {
2672                            len = -ENOMEM;
2673                            goto out;
2674                    }
2675                    kfree(head->read_buf);
2676                    head->read_buf = cp;
2677                    head->readbuf_size = len;
2678            }
2679          if (len > buffer_len)          if (len > buffer_len)
2680                  len = buffer_len;                  len = buffer_len;
2681          if (!len)          if (!len)
# Line 2373  int ccs_write_control(struct file *file, Line 2724  int ccs_write_control(struct file *file,
2724          while (avail_len > 0) {          while (avail_len > 0) {
2725                  char c;                  char c;
2726                  if (head->write_avail >= head->writebuf_size - 1) {                  if (head->write_avail >= head->writebuf_size - 1) {
2727                          error = -ENOMEM;                          const int len = head->writebuf_size * 2;
2728                          break;                          char *cp = kzalloc(len, GFP_KERNEL);
2729                  } else if (get_user(c, buffer)) {                          if (!cp) {
2730                                    error = -ENOMEM;
2731                                    break;
2732                            }
2733                            memmove(cp, cp0, head->write_avail);
2734                            kfree(cp0);
2735                            head->write_buf = cp;
2736                            cp0 = cp;
2737                            head->writebuf_size = len;
2738                    }
2739                    if (get_user(c, buffer)) {
2740                          error = -EFAULT;                          error = -EFAULT;
2741                          break;                          break;
2742                  }                  }

Legend:
Removed from v.2911  
changed lines
  Added in v.2975

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