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

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 2888 by kumaneko, Mon Aug 10 07:31:29 2009 UTC trunk/1.7.x/ccs-patch/security/ccsecurity/policy_io.c revision 2976 by kumaneko, Tue Sep 1 06:24:08 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  static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +  /* Profile table. Memory is allocated as needed. */
35                                     CCS_MAX_CAPABILITY_INDEX + 1];  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
36    
37    /* Lock for protecting "struct ccs_profile"->comment  */
38    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_MAC_FOR_IOCTL]       = { "MAC_FOR_IOCTL",       0, 3 },          = "file::open",
53          [CCS_MAC_FOR_FILEATTR]    = { "MAC_FOR_FILEATTR",    0, 3 },          [CCS_MAC_FILE_CREATE]
54          [CCS_MAC_FOR_ARGV0]       = { "MAC_FOR_ARGV0",       0, 3 },          = "file::create",
55          [CCS_MAC_FOR_ENV]         = { "MAC_FOR_ENV",         0, 3 },          [CCS_MAC_FILE_UNLINK]
56          [CCS_MAC_FOR_NETWORK]     = { "MAC_FOR_NETWORK",     0, 3 },          = "file::unlink",
57          [CCS_MAC_FOR_SIGNAL]      = { "MAC_FOR_SIGNAL",      0, 3 },          [CCS_MAC_FILE_MKDIR]
58          [CCS_MAC_FOR_NAMESPACE]   = { "MAC_FOR_NAMESPACE",   0, 3 },          = "file::mkdir",
59          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },          [CCS_MAC_FILE_RMDIR]
60          [CCS_MAX_ACCEPT_ENTRY]          = "file::rmdir",
61          = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },          [CCS_MAC_FILE_MKFIFO]
62  #ifdef CONFIG_CCSECURITY_AUDIT          = "file::mkfifo",
63          [CCS_MAX_GRANT_LOG]          [CCS_MAC_FILE_MKSOCK]
64          = { "MAX_GRANT_LOG", CONFIG_CCSECURITY_MAX_GRANT_LOG, INT_MAX },          = "file::mksock",
65          [CCS_MAX_REJECT_LOG]          [CCS_MAC_FILE_TRUNCATE]
66          = { "MAX_REJECT_LOG", CONFIG_CCSECURITY_MAX_REJECT_LOG, INT_MAX },          = "file::truncate",
67  #endif          [CCS_MAC_FILE_SYMLINK]
68          [CCS_VERBOSE]             = { "TOMOYO_VERBOSE",      1, 1 },          = "file::symlink",
69          [CCS_SLEEP_PERIOD]          [CCS_MAC_FILE_REWRITE]
70          = { "SLEEP_PERIOD",        0, 3000 }, /* in 0.1 second */          = "file::rewrite",
71            [CCS_MAC_FILE_MKBLOCK]
72            = "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 107  bool ccs_io_printf(struct ccs_io_buffer Line 248  bool ccs_io_printf(struct ccs_io_buffer
248   *   *
249   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
250   */   */
251  struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int  static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
252                                                     profile)                                                            profile)
253  {  {
254          struct ccs_profile *ptr;          struct ccs_profile *ptr;
255          struct ccs_profile *entry;          struct ccs_profile *entry;
256          int i;          if (profile >= CCS_MAX_PROFILES)
         if (profile >= MAX_PROFILES)  
257                  return NULL;                  return NULL;
258          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
259          if (ptr)          if (ptr)
# Line 123  struct ccs_profile *ccs_find_or_assign_n Line 263  struct ccs_profile *ccs_find_or_assign_n
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 139  struct ccs_profile *ccs_find_or_assign_n Line 283  struct ccs_profile *ccs_find_or_assign_n
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 149  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 (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) {          if (!strcmp(data, "CONFIG")) {
426                  if (sscanf(cp + 1, "%u", &value) != 1) {                  i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
427                          for (i = 0; i < 4; i++) {                          + CCS_MAX_MAC_CATEGORY_INDEX;
428                                  if (strcmp(cp + 1, ccs_mode_4[i]))                  config = profile->default_config;
429                                          continue;          } else if (ccs_str_starts(&data, "CONFIG::")) {
430                                  value = i;                  config = 0;
431                                  break;                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
432                          }                               + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
433                          if (i == 4)                          if (strcmp(data, ccs_mac_keywords[i]))
                                 return -EINVAL;  
                 }  
                 if (value > 3)  
                         value = 3;  
                 for (i = 0; i < CCS_MAX_CAPABILITY_INDEX; i++) {  
                         if (strcmp(data, ccs_capability_control_keyword[i]))  
434                                  continue;                                  continue;
435                          ccs_profile->capability_value[i] = value;                          config = profile->config[i];
436                          ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]                          break;
                                 = true;  
                         return 0;  
437                  }                  }
438                    if (i == CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
439                        + CCS_MAX_MAC_CATEGORY_INDEX)
440                            return -EINVAL;
441            } else {
442                  return -EINVAL;                  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_RESTRICT_AUTOBIND:                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
452                          case CCS_VERBOSE:                                   */
453                                  modes = ccs_mode_2;                                  config = (config & ~7) | mode;
454                                  break;  #ifdef CONFIG_CCSECURITY_AUDIT
455                          default:                  if (config != CCS_CONFIG_USE_DEFAULT) {
456                                  modes = ccs_mode_4;                          if (strstr(cp, "grant_log=yes"))
457                                  break;                                  config |= CCS_CONFIG_WANT_GRANT_LOG;
458                          }                          else if (strstr(cp, "grant_log=no"))
459                          for (j = 0; j < 4; j++) {                                  config &= ~CCS_CONFIG_WANT_GRANT_LOG;
460                                  if (strcmp(cp + 1, modes[j]))                          if (strstr(cp, "reject_log=yes"))
461                                          continue;                                  config |= CCS_CONFIG_WANT_REJECT_LOG;
462                                  value = j;                          else if (strstr(cp, "reject_log=no"))
463                                  break;                                  config &= ~CCS_CONFIG_WANT_REJECT_LOG;
                         }  
                         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;  
466          }          }
467          return -EINVAL;          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
468                + CCS_MAX_MAC_CATEGORY_INDEX)
469                    profile->config[i] = config;
470            else if (config != CCS_CONFIG_USE_DEFAULT)
471                    profile->default_config = config;
472            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          int index;
                 = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;  
         int step;  
483          if (head->read_eof)          if (head->read_eof)
484                  return 0;                  return;
485          for (step = head->read_step; step < MAX_PROFILES * ccs_total; step++) {          if (head->read_bit)
486                  const u8 index = step / ccs_total;                  goto body;
487                  u8 type = step % ccs_total;          ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
488                  const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];  #ifdef CONFIG_CCSECURITY_AUDIT
489                  head->read_step = step;          ccs_io_printf(head, "PREFERENCE::audit={ max_grant_log=%u "
490                  if (!ccs_profile)                        "max_reject_log=%u }\n",
491                          continue;                        ccs_default_profile.preference.audit_max_grant_log,
492                  if (!ccs_profile_entry_used[type])                        ccs_default_profile.preference.audit_max_reject_log);
493                          continue;  #endif
494                  if (!type) { /* Print profile' comment tag. */          ccs_io_printf(head, "PREFERENCE::learning={ verbose=%s max_entry=%u "
495                          bool done;                        "exec.realpath=%s exec.argv0=%s symlink.target=%s }\n",
496                          /***** CRITICAL SECTION START *****/                        ccs_yesno(ccs_default_profile.preference.
497                          spin_lock(&ccs_profile_comment_lock);                                  learning_verbose),
498                          done = ccs_io_printf(head, "%u-COMMENT=%s\n",                        ccs_default_profile.preference.learning_max_entry,
499                                               index, ccs_profile->comment ?                        ccs_yesno(ccs_default_profile.preference.
500                                               ccs_profile->comment->name : "");                                  learning_exec_realpath),
501                          spin_unlock(&ccs_profile_comment_lock);                        ccs_yesno(ccs_default_profile.preference.
502                          /***** CRITICAL SECTION END *****/                                  learning_exec_argv0),
503                          if (!done)                        ccs_yesno(ccs_default_profile.preference.
504                                  break;                                  learning_symlink_target));
505            ccs_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n",
506                          ccs_yesno(ccs_default_profile.preference.
507                                    permissive_verbose));
508            ccs_io_printf(head, "PREFERENCE::enforcing={ verbose=%s penalty=%u "
509                          "}\n",
510                          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--;  #ifdef CONFIG_CCSECURITY_AUDIT
572                  if (type >= CCS_MAX_CONTROL_INDEX) {                  if (profile->audit != &ccs_default_profile.preference &&
573                          const int i = type - CCS_MAX_CONTROL_INDEX;                      !ccs_io_printf(head, "%u-PREFERENCE::audit={ "
574                          const u8 value = ccs_profile->capability_value[i];                                     "max_grant_log=%u max_reject_log=%u }\n",
575                          if (!ccs_io_printf(head,                                     index,
576                                             "%u-" KEYWORD_MAC_FOR_CAPABILITY                                     profile->preference.audit_max_grant_log,
577                                             "%s=%s\n", index,                                     profile->preference.audit_max_reject_log))
578                                             ccs_capability_control_keyword[i],                          goto out;
579                                             ccs_mode_4[value]))  #endif
580                                  break;                  if (profile->learning != &ccs_default_profile.preference &&
581                  } else {                      !ccs_io_printf(head, "%u-PREFERENCE::learning={ "
582                          const unsigned int value = ccs_profile->value[type];                                     "verbose=%s max_entry=%u exec.realpath=%s "
583                          const char **modes = NULL;                                     "exec.argv0=%s symlink.target=%s }\n",
584                          const char *keyword = ccs_control_array[type].keyword;                                     index,
585                          switch (ccs_control_array[type].max_value) {                                     ccs_yesno(profile->preference.
586                          case 3:                                               learning_verbose),
587                                  modes = ccs_mode_4;                                     profile->preference.learning_max_entry,
588                                  break;                                     ccs_yesno(profile->preference.
589                          case 1:                                               learning_exec_realpath),
590                                  modes = ccs_mode_2;                                     ccs_yesno(profile->preference.
591                                  break;                                               learning_exec_argv0),
592                          }                                     ccs_yesno(profile->preference.
593                          if (modes) {                                               learning_symlink_target)))
594                                  if (!ccs_io_printf(head, "%u-%s=%s\n", index,                          goto out;
595                                                     keyword, modes[value]))                  if (profile->permissive != &ccs_default_profile.preference &&
596                                          break;                      !ccs_io_printf(head, "%u-PREFERENCE::permissive={ "
597                          } else {                                     "verbose=%s }\n", index,
598                                  if (!ccs_io_printf(head, "%u-%s=%u\n", index,                                     ccs_yesno(profile->preference.
599                                                     keyword, value))                                               permissive_verbose)))
600                                          break;                          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 == 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 325  static int ccs_update_manager_entry(cons Line 629  static int ccs_update_manager_entry(cons
629  {  {
630          struct ccs_policy_manager_entry *entry = NULL;          struct ccs_policy_manager_entry *entry = NULL;
631          struct ccs_policy_manager_entry *ptr;          struct ccs_policy_manager_entry *ptr;
632          const struct ccs_path_info *saved_manager;          struct ccs_policy_manager_entry e = { };
633          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
         bool is_domain = false;  
634          if (ccs_is_domain_def(manager)) {          if (ccs_is_domain_def(manager)) {
635                  if (!ccs_is_correct_domain(manager))                  if (!ccs_is_correct_domain(manager))
636                          return -EINVAL;                          return -EINVAL;
637                  is_domain = true;                  e.is_domain = true;
638          } else {          } else {
639                  if (!ccs_is_correct_path(manager, 1, -1, -1))                  if (!ccs_is_correct_path(manager, 1, -1, -1))
640                          return -EINVAL;                          return -EINVAL;
641          }          }
642          saved_manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
643          if (!saved_manager)          if (!e.manager)
644                  return -ENOMEM;                  return -ENOMEM;
645          if (!is_delete)          if (!is_delete)
646                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);                  entry = kmalloc(sizeof(e), GFP_KERNEL);
647          mutex_lock(&ccs_policy_lock);          mutex_lock(&ccs_policy_lock);
648          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
649                  if (ptr->manager != saved_manager)                  if (ptr->manager != e.manager)
650                          continue;                          continue;
651                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
652                  error = 0;                  error = 0;
653                  break;                  break;
654          }          }
655          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {          if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {
                 entry->manager = saved_manager;  
                 saved_manager = NULL;  
                 entry->is_domain = is_domain;  
656                  list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);                  list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
657                  entry = NULL;                  entry = NULL;
658                  error = 0;                  error = 0;
659          }          }
660          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
661          ccs_put_name(saved_manager);          ccs_put_name(e.manager);
662          kfree(entry);          kfree(entry);
663          return error;          return error;
664  }  }
# Line 373  static int ccs_update_manager_entry(cons Line 673  static int ccs_update_manager_entry(cons
673  static int ccs_write_manager_policy(struct ccs_io_buffer *head)  static int ccs_write_manager_policy(struct ccs_io_buffer *head)
674  {  {
675          char *data = head->write_buf;          char *data = head->write_buf;
676          bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
677          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
678                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !is_delete;
679                  return 0;                  return 0;
# Line 386  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 424  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 505  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 549  static bool ccs_is_select_one(struct ccs Line 850  static bool ccs_is_select_one(struct ccs
850          return true;          return true;
851  }  }
852    
853    static int ccs_write_domain_policy2(char *data, struct ccs_domain_info *domain,
854                                        struct ccs_condition *cond,
855                                        const bool is_delete)
856    {
857            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))
858                    return ccs_write_capability_policy(data, domain, cond,
859                                                       is_delete);
860            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))
861                    return ccs_write_network_policy(data, domain, cond, is_delete);
862            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))
863                    return ccs_write_signal_policy(data, domain, cond, is_delete);
864            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
865                    return ccs_write_env_policy(data, domain, cond, is_delete);
866            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))
867                    return ccs_write_mount_policy(data, domain, cond, is_delete);
868            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_UNMOUNT))
869                    return ccs_write_umount_policy(data, domain, cond, is_delete);
870            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CHROOT))
871                    return ccs_write_chroot_policy(data, domain, cond, is_delete);
872            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_PIVOT_ROOT))
873                    return ccs_write_pivot_root_policy(data, domain, cond,
874                                                       is_delete);
875            return ccs_write_file_policy(data, domain, cond, is_delete);
876    }
877    
878  /**  /**
879   * ccs_write_domain_policy - Write domain policy.   * ccs_write_domain_policy - Write domain policy.
880   *   *
# Line 566  static int ccs_write_domain_policy(struc Line 892  static int ccs_write_domain_policy(struc
892          struct ccs_condition *cond = NULL;          struct ccs_condition *cond = NULL;
893          char *cp;          char *cp;
894          int error;          int error;
895          if (ccs_str_starts(&data, KEYWORD_DELETE))          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
896                  is_delete = true;                  is_delete = true;
897          else if (ccs_str_starts(&data, KEYWORD_SELECT))          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
898                  is_select = true;                  is_select = true;
899          if (is_select && ccs_is_select_one(head, data))          if (is_select && ccs_is_select_one(head, data))
900                  return 0;                  return 0;
# Line 589  static int ccs_write_domain_policy(struc Line 915  static int ccs_write_domain_policy(struc
915          if (!domain)          if (!domain)
916                  return -EINVAL;                  return -EINVAL;
917    
918          if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1          if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
919              && profile < 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          }          }
924          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
925                  domain->ignore_global_allow_read = !is_delete;                  domain->ignore_global_allow_read = !is_delete;
926                  return 0;                  return 0;
927          }          }
928          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
929                  domain->ignore_global_allow_env = !is_delete;                  domain->ignore_global_allow_env = !is_delete;
930                  return 0;                  return 0;
931          }          }
# Line 609  static int ccs_write_domain_policy(struc Line 935  static int ccs_write_domain_policy(struc
935                  if (!cond)                  if (!cond)
936                          return -EINVAL;                          return -EINVAL;
937          }          }
938          if (ccs_str_starts(&data, KEYWORD_ALLOW_CAPABILITY))          error = ccs_write_domain_policy2(data, domain, cond, is_delete);
                 error = ccs_write_capability_policy(data, domain, cond,  
                                                     is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_NETWORK))  
                 error = ccs_write_network_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_SIGNAL))  
                 error = ccs_write_signal_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_ARGV0))  
                 error = ccs_write_argv0_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))  
                 error = ccs_write_env_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_MOUNT))  
                 error = ccs_write_mount_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_UNMOUNT))  
                 error = ccs_write_umount_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_CHROOT))  
                 error = ccs_write_chroot_policy(data, domain, cond, is_delete);  
         else if (ccs_str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT))  
                 error = ccs_write_pivot_root_policy(data, domain, cond,  
                                                     is_delete);  
         else  
                 error = ccs_write_file_policy(data, domain, cond, is_delete);  
939          if (cond)          if (cond)
940                  ccs_put_condition(cond);                  ccs_put_condition(cond);
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                                   struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
954  {  {
955          const int pos = head->read_avail;          int pos = head->read_avail;
956          if (pos && head->read_buf[pos - 1] == ' ')          if (pos && head->read_buf[pos - 1] == ' ')
957                  head->read_avail--;                  head->read_avail--;
958          if (ptr->is_group)          if (ptr->is_group)
# Line 648  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  static bool ccs_print_number_union(struct ccs_io_buffer *head,  /**
965                                     struct ccs_number_union *ptr)   * 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,
973                                            const struct ccs_name_union *ptr)
974    {
975            if (ptr->is_group)
976                    return ccs_io_printf(head, "@%s",
977                                         ptr->group->group_name->name);
978            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,
991                                              const struct ccs_number_union *ptr,
992                                              const bool need_space)
993  {  {
994          unsigned long min;          unsigned long min;
995          unsigned long max;          unsigned long max;
996            u8 min_type;
997            u8 max_type;
998            if (need_space && !ccs_io_printf(head, " "))
999                    return false;
1000          if (ptr->is_group)          if (ptr->is_group)
1001                  return ccs_io_printf(head, " @%s",                  return ccs_io_printf(head, "@%s",
1002                                       ptr->group->group_name->name);                                       ptr->group->group_name->name);
1003            min_type = ptr->min_type;
1004            max_type = ptr->max_type;
1005          min = ptr->values[0];          min = ptr->values[0];
1006          max = ptr->values[1];          max = ptr->values[1];
1007          if (min == max)          switch (min_type) {
1008                  return ccs_io_printf(head, " %lu", min);          case CCS_VALUE_TYPE_HEXADECIMAL:
1009          return ccs_io_printf(head, " %lu-%lu", min, max);                  if (!ccs_io_printf(head, "0x%lX", min))
1010                            return false;
1011                    break;
1012            case CCS_VALUE_TYPE_OCTAL:
1013                    if (!ccs_io_printf(head, "0%lo", min))
1014                            return false;
1015                    break;
1016            default:
1017                    if (!ccs_io_printf(head, "%lu", min))
1018                            return false;
1019                    break;
1020            }
1021            if (min == max && min_type == max_type)
1022                    return true;
1023            switch (max_type) {
1024            case CCS_VALUE_TYPE_HEXADECIMAL:
1025                    return ccs_io_printf(head, "-0x%lX", max);
1026            case CCS_VALUE_TYPE_OCTAL:
1027                    return ccs_io_printf(head, "-0%lo", max);
1028            default:
1029                    return ccs_io_printf(head, "-%lu", max);
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,
1042                                const struct ccs_number_union *ptr)
1043    {
1044            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,
1056                                               const struct ccs_number_union *ptr)
1057    {
1058            return ccs_print_number_union_common(head, ptr, false);
1059  }  }
1060    
1061  /**  /**
1062   * ccs_print_single_path_acl - Print a single path ACL entry.   * ccs_print_condition - Print condition part.
1063   *   *
1064   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  * @ptr:  Pointer to "struct ccs_single_path_acl_record".  
1065   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1066   *   *
1067   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1068   */   */
1069  static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_condition(struct ccs_io_buffer *head,
1070                                        struct ccs_single_path_acl_record *ptr,                                  const struct ccs_condition *cond)
1071                                        const struct ccs_condition *cond)  {
1072            const struct ccs_condition_element *condp;
1073            const struct ccs_number_union *numbers_p;
1074            const struct ccs_name_union *names_p;
1075            const struct ccs_argv_entry *argv;
1076            const struct ccs_envp_entry *envp;
1077            u16 condc;
1078            u16 i;
1079            u16 j;
1080            char buffer[32];
1081            if (!cond)
1082                    goto no_condition;
1083            condc = cond->condc;
1084            condp = (const struct ccs_condition_element *) (cond + 1);
1085            numbers_p = (const struct ccs_number_union *) (condp + condc);
1086            names_p = (const struct ccs_name_union *)
1087                    (numbers_p + cond->numbers_count);
1088            argv = (const struct ccs_argv_entry *) (names_p + cond->names_count);
1089            envp = (const struct ccs_envp_entry *) (argv + cond->argc);
1090            memset(buffer, 0, sizeof(buffer));
1091            if (condc && !ccs_io_printf(head, "%s", " if"))
1092                    goto out;
1093            for (i = 0; i < condc; i++) {
1094                    const u8 match = condp->equals;
1095                    const u8 left = condp->left;
1096                    const u8 right = condp->right;
1097                    condp++;
1098                    switch (left) {
1099                    case CCS_ARGV_ENTRY:
1100                            if (!ccs_io_printf(head, " exec.argv[%u]%s\"%s\"",
1101                                               argv->index, argv->is_not ?
1102                                               "!=" : "=", argv->value->name))
1103                                    goto out;
1104                            argv++;
1105                            continue;
1106                    case CCS_ENVP_ENTRY:
1107                            if (!ccs_io_printf(head, " exec.envp[\"%s\"]%s",
1108                                               envp->name->name, envp->is_not ?
1109                                               "!=" : "="))
1110                                    goto out;
1111                            if (envp->value) {
1112                                    if (!ccs_io_printf(head, "\"%s\"",
1113                                                       envp->value->name))
1114                                            goto out;
1115                            } else {
1116                                    if (!ccs_io_printf(head, "NULL"))
1117                                            goto out;
1118                            }
1119                            envp++;
1120                            continue;
1121                    case CCS_NUMBER_UNION:
1122                            if (!ccs_print_number_union(head, numbers_p++))
1123                                    goto out;
1124                            break;
1125                    default:
1126                            if (left >= CCS_MAX_CONDITION_KEYWORD)
1127                                    goto out;
1128                            if (!ccs_io_printf(head, " %s",
1129                                               ccs_condition_keyword[left]))
1130                                    goto out;
1131                            break;
1132                    }
1133                    if (!ccs_io_printf(head, "%s", match ? "=" : "!="))
1134                            goto out;
1135                    switch (right) {
1136                    case CCS_NAME_UNION:
1137                            if (!ccs_print_name_union_quoted(head, names_p++))
1138                                    goto out;
1139                            break;
1140                    case CCS_NUMBER_UNION:
1141                            if (!ccs_print_number_union_nospace(head, numbers_p++))
1142                                    goto out;
1143                            break;
1144                    default:
1145                            if (right >= CCS_MAX_CONDITION_KEYWORD)
1146                                    goto out;
1147                            if (!ccs_io_printf(head, "%s",
1148                                               ccs_condition_keyword[right]))
1149                                    goto out;
1150                            break;
1151                    }
1152            }
1153            i = cond->post_state[3];
1154            if (!i)
1155                    goto no_condition;
1156            if (!ccs_io_printf(head, " ; set"))
1157                    goto out;
1158            for (j = 0; j < 3; j++) {
1159                    if (!(i & (1 << j)))
1160                            continue;
1161                    if (!ccs_io_printf(head, " task.state[%u]=%u", j,
1162                                       cond->post_state[j]))
1163                            goto out;
1164            }
1165     no_condition:
1166            if (ccs_io_printf(head, "\n"))
1167                    return true;
1168     out:
1169            return false;
1170    }
1171    
1172    /**
1173     * ccs_print_path_acl - Print a single path ACL entry.
1174     *
1175     * @head: Pointer to "struct ccs_io_buffer".
1176     * @ptr:  Pointer to "struct ccs_path_acl".
1177     * @cond: Pointer to "struct ccs_condition". May be NULL.
1178     *
1179     * Returns true on success, false otherwise.
1180     */
1181    static bool ccs_print_path_acl(struct ccs_io_buffer *head,
1182                                   struct ccs_path_acl *ptr,
1183                                   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 < 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 != 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 == TYPE_READ_ACL || bit == TYPE_WRITE_ACL)                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
1195                      && (perm & (1 << 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                          goto out;                          head->read_bit = bit;
1202                            head->read_avail = pos;
1203                            return false;
1204                    }
1205          }          }
1206          head->read_bit = 0;          head->read_bit = 0;
1207          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
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 < 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)) {
1238                          goto out;                          head->read_bit = bit;
1239                            head->read_avail = pos;
1240                            return false;
1241                    }
1242          }          }
1243          head->read_bit = 0;          head->read_bit = 0;
1244          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
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 < 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)) {
1272                          goto out;                          head->read_bit = bit;
1273                            head->read_avail = pos;
1274                            return false;
1275                    }
1276          }          }
1277          head->read_bit = 0;          head->read_bit = 0;
1278          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
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 < 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)) {
1307                          goto out;                          head->read_bit = bit;
1308                            head->read_avail = pos;
1309                            return false;
1310                    }
1311          }          }
1312          head->read_bit = 0;          head->read_bit = 0;
1313          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
 }  
   
 /**  
  * ccs_print_argv0_acl - Print an argv[0] ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_argv0_acl_record".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_argv0_acl(struct ccs_io_buffer *head,  
                                 struct ccs_argv0_acl_record *ptr,  
                                 const struct ccs_condition *cond)  
 {  
         int pos = head->read_avail;  
         if (!ccs_io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s",  
                            ptr->filename->name, ptr->argv0->name))  
                 goto out;  
         if (!ccs_print_condition(head, cond))  
                 goto out;  
         return true;  
  out:  
         head->read_avail = pos;  
         return false;  
1314  }  }
1315    
1316  /**  /**
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          int pos = head->read_avail;          const int pos = head->read_avail;
1330          if (!ccs_io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name))          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) ||
1331                  goto out;              !ccs_print_condition(head, cond)) {
1332          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1333                  goto out;                  return false;
1334            }
1335          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1336  }  }
1337    
1338  /**  /**
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          int pos = head->read_avail;          const int pos = head->read_avail;
1352          if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1353                             ccs_cap2keyword(ptr->operation)))                             ccs_cap2keyword(ptr->operation)) ||
1354                  goto out;              !ccs_print_condition(head, cond)) {
1355          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1356                  goto out;                  return false;
1357            }
1358          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1359  }  }
1360    
1361  /**  /**
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 912  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 937  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          int pos = head->read_avail;          int pos;
1421          if (!ccs_io_printf(head, 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 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 IP_RECORD_TYPE_IPv4:  
                 if (!ccs_print_ipv4_entry(head, ptr))  
1429                          goto out;                          goto out;
1430                  break;                  switch (ptr->address_type) {
1431          case 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 978  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          int pos = head->read_avail;          const int pos = head->read_avail;
1471          if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1472                             ptr->sig, ptr->domainname->name))                             ptr->sig, ptr->domainname->name) ||
1473                  goto out;              !ccs_print_condition(head, cond)) {
1474          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1475                  goto out;                  return false;
1476            }
1477          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1478  }  }
1479    
1480  /**  /**
# Line 1020  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          int pos = head->read_avail;          const int pos = head->read_avail;
1511          if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
1512                             ptr->dev_name->name, ptr->dir_name->name,              !ccs_print_name_union(head, &ptr->dev_name) ||
1513                             ptr->fs_type->name, ptr->flags))              !ccs_print_name_union(head, &ptr->dir_name) ||
1514                  goto out;              !ccs_print_name_union(head, &ptr->fs_type) ||
1515          if (!ccs_print_condition(head, cond))              !ccs_print_number_union(head, &ptr->flags) ||
1516                  goto out;              !ccs_print_condition(head, cond)) {
1517                    head->read_avail = pos;
1518                    return false;
1519            }
1520          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1521  }  }
1522    
1523  /**  /**
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          int pos = head->read_avail;          const int pos = head->read_avail;
1537          if (!ccs_io_printf(head, KEYWORD_ALLOW_UNMOUNT "%s\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_UNMOUNT) ||
1538                             ptr->dir->name))              !ccs_print_name_union(head, &ptr->dir) ||
1539                  goto out;              !ccs_print_condition(head, cond)) {
1540          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1541                  goto out;                  return false;
1542            }
1543          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1544  }  }
1545    
1546  /**  /**
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          int pos = head->read_avail;          const int pos = head->read_avail;
1560          if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CHROOT) ||
1561                             ptr->dir->name))              !ccs_print_name_union(head, &ptr->dir) ||
1562                  goto out;              !ccs_print_condition(head, cond)) {
1563          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1564                  goto out;                  return false;
1565            }
1566          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1567  }  }
1568    
1569  /**  /**
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          int pos = head->read_avail;          const int pos = head->read_avail;
1583          if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_PIVOT_ROOT) ||
1584                             ptr->new_root->name, ptr->old_root->name))              !ccs_print_name_union(head, &ptr->new_root) ||
1585                  goto out;              !ccs_print_name_union(head, &ptr->old_root) ||
1586          if (!ccs_print_condition(head, cond))              !ccs_print_condition(head, cond)) {
1587                  goto out;                  head->read_avail = pos;
1588                    return false;
1589            }
1590          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1591  }  }
1592    
1593  /**  /**
# Line 1129  static bool ccs_print_entry(struct ccs_i Line 1602  static bool ccs_print_entry(struct ccs_i
1602                              struct ccs_acl_info *ptr)                              struct ccs_acl_info *ptr)
1603  {  {
1604          const struct ccs_condition *cond = ptr->cond;          const struct ccs_condition *cond = ptr->cond;
1605          const u8 acl_type = ccs_acl_type2(ptr);          const u8 acl_type = ptr->type;
1606          if (acl_type & ACL_DELETED)          if (ptr->is_deleted)
1607                  return true;                  return true;
1608          if (acl_type == 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 == TYPE_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1615                  struct ccs_execute_handler_record *acl                  struct ccs_execute_handler_record *acl
1616                          = container_of(ptr, struct ccs_execute_handler_record,                          = container_of(ptr, struct ccs_execute_handler_record,
1617                                         head);                                         head);
1618                  const char *keyword = KEYWORD_EXECUTE_HANDLER;                  const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;
1619                  return ccs_print_execute_handler_record(head, keyword, acl);                  return ccs_print_execute_handler_record(head, keyword, acl);
1620          }          }
1621          if (acl_type == TYPE_DENIED_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1622                  struct ccs_execute_handler_record *acl                  struct ccs_execute_handler_record *acl
1623                          = container_of(ptr, struct ccs_execute_handler_record,                          = container_of(ptr, struct ccs_execute_handler_record,
1624                                         head);                                         head);
1625                  const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER;                  const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER;
1626                  return ccs_print_execute_handler_record(head, keyword, acl);                  return ccs_print_execute_handler_record(head, keyword, acl);
1627          }          }
1628          if (head->read_execute_only)          if (head->read_execute_only)
1629                  return true;                  return true;
1630          if (acl_type == 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 == 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 == 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 == TYPE_ARGV0_ACL) {          if (acl_type == CCS_TYPE_ENV_ACL) {
1648                  struct ccs_argv0_acl_record *acl                  struct ccs_env_acl *acl
1649                          = container_of(ptr, struct ccs_argv0_acl_record, head);                          = container_of(ptr, struct ccs_env_acl, head);
                 return ccs_print_argv0_acl(head, acl, cond);  
         }  
         if (acl_type == TYPE_ENV_ACL) {  
                 struct ccs_env_acl_record *acl  
                         = container_of(ptr, struct ccs_env_acl_record, head);  
1650                  return ccs_print_env_acl(head, acl, cond);                  return ccs_print_env_acl(head, acl, cond);
1651          }          }
1652          if (acl_type == 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 == 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 == 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 == 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 == 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 == 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 == 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          }          }
         /* Workaround for gcc 3.2.2's inline bug. */  
         if (acl_type & ACL_DELETED)  
                 return true;  
1690          BUG(); /* This must not happen. */          BUG(); /* This must not happen. */
1691          return false;          return false;
1692  }  }
# Line 1231  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 1262  static int ccs_read_domain_policy(struct Line 1724  static int ccs_read_domain_policy(struct
1724                          transition_failed = "transition_failed\n";                          transition_failed = "transition_failed\n";
1725                  if (domain->ignore_global_allow_read)                  if (domain->ignore_global_allow_read)
1726                          ignore_global_allow_read                          ignore_global_allow_read
1727                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1728                  if (domain->ignore_global_allow_env)                  if (domain->ignore_global_allow_env)
1729                          ignore_global_allow_env                          ignore_global_allow_env
1730                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
1731                  if (!ccs_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n"                  if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n"
1732                                     "%s%s%s%s\n", domain->domainname->name,                                     "%s%s%s%s\n", domain->domainname->name,
1733                                     domain->profile, quota_exceeded,                                     domain->profile, quota_exceeded,
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 1283  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 1307  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 1317  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';
1784          profile = simple_strtoul(data, NULL, 10);          profile = simple_strtoul(data, NULL, 10);
1785          if (profile >= 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 1335  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 1346  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 1359  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 1389  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 1445  static int ccs_read_pid(struct ccs_io_bu Line 1906  static int ccs_read_pid(struct ccs_io_bu
1906  static int ccs_write_exception_policy(struct ccs_io_buffer *head)  static int ccs_write_exception_policy(struct ccs_io_buffer *head)
1907  {  {
1908          char *data = head->write_buf;          char *data = head->write_buf;
1909          bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1910          if (ccs_str_starts(&data, KEYWORD_KEEP_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN))
1911                  return ccs_write_domain_keeper_policy(data, false, is_delete);                  return ccs_write_domain_keeper_policy(data, false, is_delete);
1912          if (ccs_str_starts(&data, KEYWORD_NO_KEEP_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN))
1913                  return ccs_write_domain_keeper_policy(data, true, is_delete);                  return ccs_write_domain_keeper_policy(data, true, is_delete);
1914          if (ccs_str_starts(&data, KEYWORD_INITIALIZE_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN))
1915                  return ccs_write_domain_initializer_policy(data, false,                  return ccs_write_domain_initializer_policy(data, false,
1916                                                             is_delete);                                                             is_delete);
1917          if (ccs_str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN))
1918                  return ccs_write_domain_initializer_policy(data, true,                  return ccs_write_domain_initializer_policy(data, true,
1919                                                             is_delete);                                                             is_delete);
1920          if (ccs_str_starts(&data, KEYWORD_AGGREGATOR))          if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR))
1921                  return ccs_write_aggregator_policy(data, is_delete);                  return ccs_write_aggregator_policy(data, is_delete);
1922          if (ccs_str_starts(&data, KEYWORD_ALLOW_READ))          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ))
1923                  return ccs_write_globally_readable_policy(data, is_delete);                  return ccs_write_globally_readable_policy(data, is_delete);
1924          if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
1925                  return ccs_write_globally_usable_env_policy(data, is_delete);                  return ccs_write_globally_usable_env_policy(data, is_delete);
1926          if (ccs_str_starts(&data, KEYWORD_FILE_PATTERN))          if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN))
1927                  return ccs_write_pattern_policy(data, is_delete);                  return ccs_write_pattern_policy(data, is_delete);
1928          if (ccs_str_starts(&data, KEYWORD_PATH_GROUP))          if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP))
1929                  return ccs_write_path_group_policy(data, is_delete);                  return ccs_write_path_group_policy(data, is_delete);
1930          if (ccs_str_starts(&data, KEYWORD_NUMBER_GROUP))          if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP))
1931                  return ccs_write_number_group_policy(data, is_delete);                  return ccs_write_number_group_policy(data, is_delete);
1932          if (ccs_str_starts(&data, KEYWORD_DENY_REWRITE))          if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE))
1933                  return ccs_write_no_rewrite_policy(data, is_delete);                  return ccs_write_no_rewrite_policy(data, is_delete);
1934          if (ccs_str_starts(&data, KEYWORD_ADDRESS_GROUP))          if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP))
1935                  return ccs_write_address_group_policy(data, is_delete);                  return ccs_write_address_group_policy(data, is_delete);
1936          if (ccs_str_starts(&data, KEYWORD_DENY_AUTOBIND))          if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND))
1937                  return ccs_write_reserved_port_policy(data, is_delete);                  return ccs_write_reserved_port_policy(data, is_delete);
1938          return -EINVAL;          return -EINVAL;
1939  }  }
# Line 1482  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))
1958                                  break;                          break;
1959                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1960                          head->read_step = 2;                  head->read_step = 2;
1961                  case 2:          case 2:
1962                          if (!ccs_read_globally_readable_policy(head))                  if (!ccs_read_globally_readable_policy(head))
1963                                  break;                          break;
1964                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1965                          head->read_step = 3;                  head->read_step = 3;
1966                  case 3:          case 3:
1967                          if (!ccs_read_globally_usable_env_policy(head))                  if (!ccs_read_globally_usable_env_policy(head))
1968                                  break;                          break;
1969                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1970                          head->read_step = 4;                  head->read_step = 4;
1971                  case 4:          case 4:
1972                          if (!ccs_read_domain_initializer_policy(head))                  if (!ccs_read_domain_initializer_policy(head))
1973                                  break;                          break;
1974                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1975                          head->read_step = 6;                  head->read_step = 6;
1976                  case 6:          case 6:
1977                          if (!ccs_read_aggregator_policy(head))                  if (!ccs_read_aggregator_policy(head))
1978                                  break;                          break;
1979                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1980                          head->read_step = 7;                  head->read_step = 7;
1981                  case 7:          case 7:
1982                          if (!ccs_read_file_pattern(head))                  if (!ccs_read_file_pattern(head))
1983                                  break;                          break;
1984                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1985                          head->read_step = 8;                  head->read_step = 8;
1986                  case 8:          case 8:
1987                          if (!ccs_read_no_rewrite_policy(head))                  if (!ccs_read_no_rewrite_policy(head))
1988                                  break;                          break;
1989                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1990                          head->read_step = 9;                  head->read_step = 9;
1991                  case 9:          case 9:
1992                          if (!ccs_read_path_group_policy(head))                  if (!ccs_read_path_group_policy(head))
1993                                  break;                          break;
1994                          head->read_var1 = NULL;                  head->read_var1 = NULL;
1995                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1996                          head->read_step = 10;                  head->read_step = 10;
1997                  case 10:          case 10:
1998                          if (!ccs_read_number_group_policy(head))                  if (!ccs_read_number_group_policy(head))
1999                                  break;                          break;
2000                          head->read_var1 = NULL;                  head->read_var1 = NULL;
2001                          head->read_var2 = NULL;                  head->read_var2 = NULL;
2002                          head->read_step = 11;                  head->read_step = 11;
2003                  case 11:          case 11:
2004                          if (!ccs_read_address_group_policy(head))                  if (!ccs_read_address_group_policy(head))
2005                                  break;                          break;
2006                          head->read_var2 = NULL;                  head->read_var2 = NULL;
2007                          head->read_step = 12;                  head->read_step = 12;
2008                  case 12:          case 12:
2009                          if (!ccs_read_reserved_port_policy(head))                  if (!ccs_read_reserved_port_policy(head))
2010                            break;
2011                    head->read_eof = true;
2012            }
2013    }
2014    
2015    /**
2016     * ccs_get_argv0 - Get argv[0].
2017     *
2018     * @ee: Pointer to "struct ccs_execve_entry".
2019     *
2020     * Returns true on success, false otherwise.
2021     */
2022    static bool ccs_get_argv0(struct ccs_execve_entry *ee)
2023    {
2024            struct linux_binprm *bprm = ee->bprm;
2025            char *arg_ptr = ee->tmp;
2026            int arg_len = 0;
2027            unsigned long pos = bprm->p;
2028            int offset = pos % PAGE_SIZE;
2029            bool done = false;
2030            if (!bprm->argc)
2031                    goto out;
2032            while (1) {
2033                    if (!ccs_dump_page(bprm, pos, &ee->dump))
2034                            goto out;
2035                    pos += PAGE_SIZE - offset;
2036                    /* Read. */
2037                    while (offset < PAGE_SIZE) {
2038                            const char *kaddr = ee->dump.data;
2039                            const unsigned char c = kaddr[offset++];
2040                            if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
2041                                    if (c == '\\') {
2042                                            arg_ptr[arg_len++] = '\\';
2043                                            arg_ptr[arg_len++] = '\\';
2044                                    } else if (c > ' ' && c < 127) {
2045                                            arg_ptr[arg_len++] = c;
2046                                    } else {
2047                                            arg_ptr[arg_len++] = '\\';
2048                                            arg_ptr[arg_len++] = (c >> 6) + '0';
2049                                            arg_ptr[arg_len++]
2050                                                    = ((c >> 3) & 7) + '0';
2051                                            arg_ptr[arg_len++] = (c & 7) + '0';
2052                                    }
2053                            } else {
2054                                    arg_ptr[arg_len] = '\0';
2055                                    done = true;
2056                                  break;                                  break;
2057                          head->read_eof = true;                          }
2058                    }
2059                    offset = 0;
2060                    if (done)
2061                          break;                          break;
2062                  default:          }
2063                          return -EINVAL;          return true;
2064     out:
2065            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
2076                                                           *ee)
2077    {
2078            struct ccs_condition *cond;
2079            char *buf;
2080            int len = 256;
2081            char *realpath = NULL;
2082            char *argv0 = NULL;
2083            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;
2086    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2087                    struct path path = { file->f_vfsmnt, file->f_dentry };
2088                    realpath = ccs_realpath_from_path(&path);
2089    #else
2090                    realpath = ccs_realpath_from_path(&file->f_path);
2091    #endif
2092                    if (realpath)
2093                            len += strlen(realpath) + 17;
2094            }
2095            if (profile->learning->learning_exec_argv0) {
2096                    if (ccs_get_argv0(ee)) {
2097                            argv0 = ee->tmp;
2098                            len += strlen(argv0) + 16;
2099                  }                  }
2100          }          }
2101          return 0;          buf = kmalloc(len, GFP_KERNEL);
2102            if (!buf) {
2103                    kfree(realpath);
2104                    return NULL;
2105            }
2106            snprintf(buf, len - 1, "if");
2107            if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
2108                    const int pos = strlen(buf);
2109                    snprintf(buf + pos, len - pos - 1,
2110                             " task.type=execute_handler");
2111            }
2112            if (realpath) {
2113                    const int pos = strlen(buf);
2114                    snprintf(buf + pos, len - pos - 1, " exec.realpath=\"%s\"",
2115                             realpath);
2116                    kfree(realpath);
2117            }
2118            if (argv0) {
2119                    const int pos = strlen(buf);
2120                    snprintf(buf + pos, len - pos - 1, " exec.argv[0]=\"%s\"",
2121                             argv0);
2122            }
2123            cond = ccs_get_condition(buf);
2124            kfree(buf);
2125            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. */
# Line 1581  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 1589  static atomic_t ccs_query_observers = AT Line 2194  static atomic_t ccs_query_observers = AT
2194   * Returns 0 if the supervisor decided to permit the access request which   * Returns 0 if the supervisor decided to permit the access request which
2195   * violated the policy in enforcing mode, 1 if the supervisor decided to   * violated the policy in enforcing mode, 1 if the supervisor decided to
2196   * retry the access request which violated the policy in enforcing mode,   * retry the access request which violated the policy in enforcing mode,
2197   * -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 1603  int ccs_check_supervisor(struct ccs_requ Line 2208  int ccs_check_supervisor(struct ccs_requ
2208          char *header;          char *header;
2209          if (!r->domain)          if (!r->domain)
2210                  r->domain = ccs_current_domain();                  r->domain = ccs_current_domain();
2211            switch (r->mode) {
2212                    char *buffer;
2213                    struct ccs_condition *cond;
2214            case CCS_CONFIG_LEARNING:
2215                    if (!ccs_domain_quota_ok(r))
2216                            return 0;
2217                    va_start(args, fmt);
2218                    len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
2219                    va_end(args);
2220                    buffer = kmalloc(len, GFP_KERNEL);
2221                    if (!buffer)
2222                            return 0;
2223                    va_start(args, fmt);
2224                    vsnprintf(buffer, len - 1, fmt, args);
2225                    va_end(args);
2226                    ccs_normalize_line(buffer);
2227                    if (r->ee && !strncmp(buffer, "allow_execute ", 14))
2228                            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)) {
2232                            char str[] = "if task.type=execute_handler";
2233                            cond = ccs_get_condition(str);
2234                    } else
2235                            cond = NULL;
2236                    ccs_write_domain_policy2(buffer, r->domain, cond, false);
2237                    ccs_put_condition(cond);
2238                    kfree(buffer);
2239                    /* fall through */
2240            case CCS_CONFIG_PERMISSIVE:
2241                    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 1623  int ccs_check_supervisor(struct ccs_requ Line 2260  int ccs_check_supervisor(struct ccs_requ
2260          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
2261          if (!ccs_query_entry)          if (!ccs_query_entry)
2262                  goto out;                  goto out;
2263            len = ccs_round2(len);
2264          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
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 1637  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 1648  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 1663  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 1709  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 1720  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 1734  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 1763  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 1790  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 1799  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 1815  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 1823  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 1838  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 1846  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 1962  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 1983  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 2004  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 2019  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 2052  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 2106  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.2888  
changed lines
  Added in v.2976

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