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

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 3131 by kumaneko, Tue Nov 3 03:51:07 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.1-pre   2009/11/03
7   *   *
8   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
9   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 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            .audit = &ccs_default_profile.preference,
20    #ifdef CONFIG_CCSECURITY_AUDIT
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.audit_task_info = true,
25            .preference.audit_path_info = true,
26            .preference.enforcing_penalty = 0,
27            .preference.enforcing_verbose = true,
28            .preference.learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY,
29            .preference.learning_verbose = false,
30            .preference.learning_exec_realpath = true,
31            .preference.learning_exec_argv0 = true,
32            .preference.learning_symlink_target = true,
33            .preference.permissive_verbose = true
34    };
35    
36  static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +  /* Profile table. Memory is allocated as needed. */
37                                     CCS_MAX_CAPABILITY_INDEX + 1];  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
38    
39  /* String table for functionality that takes 4 modes. */  /* String table for functionality that takes 4 modes. */
40  static const char *ccs_mode_4[4] = {  static const char *ccs_mode_4[4] = {
41          "disabled", "learning", "permissive", "enforcing"          "disabled", "learning", "permissive", "enforcing"
42  };  };
 /* String table for functionality that takes 2 modes. */  
 static const char *ccs_mode_2[4] = {  
         "disabled", "enabled", "enabled", "enabled"  
 };  
43    
44  /* Table for profile. */  /* String table for /proc/ccs/profile */
45  static struct {  static const char *ccs_mac_keywords[CCS_MAX_MAC_INDEX +
46          const char *keyword;                                      CCS_MAX_CAPABILITY_INDEX +
47          unsigned int current_value;                                      CCS_MAX_MAC_CATEGORY_INDEX] = {
48          const unsigned int max_value;          [CCS_MAC_FILE_EXECUTE]
49  } ccs_control_array[CCS_MAX_CONTROL_INDEX] = {          = "file::execute",
50          [CCS_MAC_FOR_FILE]        = { "MAC_FOR_FILE",        0, 3 },          [CCS_MAC_FILE_OPEN]
51          [CCS_MAC_FOR_IOCTL]       = { "MAC_FOR_IOCTL",       0, 3 },          = "file::open",
52          [CCS_MAC_FOR_FILEATTR]    = { "MAC_FOR_FILEATTR",    0, 3 },          [CCS_MAC_FILE_CREATE]
53          [CCS_MAC_FOR_ARGV0]       = { "MAC_FOR_ARGV0",       0, 3 },          = "file::create",
54          [CCS_MAC_FOR_ENV]         = { "MAC_FOR_ENV",         0, 3 },          [CCS_MAC_FILE_UNLINK]
55          [CCS_MAC_FOR_NETWORK]     = { "MAC_FOR_NETWORK",     0, 3 },          = "file::unlink",
56          [CCS_MAC_FOR_SIGNAL]      = { "MAC_FOR_SIGNAL",      0, 3 },          [CCS_MAC_FILE_MKDIR]
57          [CCS_MAC_FOR_NAMESPACE]   = { "MAC_FOR_NAMESPACE",   0, 3 },          = "file::mkdir",
58          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },          [CCS_MAC_FILE_RMDIR]
59          [CCS_MAX_ACCEPT_ENTRY]          = "file::rmdir",
60          = { "MAX_ACCEPT_ENTRY", CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY, INT_MAX },          [CCS_MAC_FILE_MKFIFO]
61  #ifdef CONFIG_CCSECURITY_AUDIT          = "file::mkfifo",
62          [CCS_MAX_GRANT_LOG]          [CCS_MAC_FILE_MKSOCK]
63          = { "MAX_GRANT_LOG", CONFIG_CCSECURITY_MAX_GRANT_LOG, INT_MAX },          = "file::mksock",
64          [CCS_MAX_REJECT_LOG]          [CCS_MAC_FILE_TRUNCATE]
65          = { "MAX_REJECT_LOG", CONFIG_CCSECURITY_MAX_REJECT_LOG, INT_MAX },          = "file::truncate",
66  #endif          [CCS_MAC_FILE_SYMLINK]
67          [CCS_VERBOSE]             = { "TOMOYO_VERBOSE",      1, 1 },          = "file::symlink",
68          [CCS_SLEEP_PERIOD]          [CCS_MAC_FILE_REWRITE]
69          = { "SLEEP_PERIOD",        0, 3000 }, /* in 0.1 second */          = "file::rewrite",
70            [CCS_MAC_FILE_MKBLOCK]
71            = "file::mkblock",
72            [CCS_MAC_FILE_MKCHAR]
73            = "file::mkchar",
74            [CCS_MAC_FILE_LINK]
75            = "file::link",
76            [CCS_MAC_FILE_RENAME]
77            = "file::rename",
78            [CCS_MAC_FILE_CHMOD]
79            = "file::chmod",
80            [CCS_MAC_FILE_CHOWN]
81            = "file::chown",
82            [CCS_MAC_FILE_CHGRP]
83            = "file::chgrp",
84            [CCS_MAC_FILE_IOCTL]
85            = "file::ioctl",
86            [CCS_MAC_FILE_CHROOT]
87            = "file::chroot",
88            [CCS_MAC_FILE_MOUNT]
89            = "file::mount",
90            [CCS_MAC_FILE_UMOUNT]
91            = "file::umount",
92            [CCS_MAC_FILE_PIVOT_ROOT]
93            = "file::pivot_root",
94            [CCS_MAC_ENVIRON]
95            = "misc::env",
96            [CCS_MAC_NETWORK_UDP_BIND]
97            = "network::inet_udp_bind",
98            [CCS_MAC_NETWORK_UDP_CONNECT]
99            = "network::inet_udp_connect",
100            [CCS_MAC_NETWORK_TCP_BIND]
101            = "network::inet_tcp_bind",
102            [CCS_MAC_NETWORK_TCP_LISTEN]
103            = "network::inet_tcp_listen",
104            [CCS_MAC_NETWORK_TCP_CONNECT]
105            = "network::inet_tcp_connect",
106            [CCS_MAC_NETWORK_TCP_ACCEPT]
107            = "network::inet_tcp_accept",
108            [CCS_MAC_NETWORK_RAW_BIND]
109            = "network::inet_raw_bind",
110            [CCS_MAC_NETWORK_RAW_CONNECT]
111            = "network::inet_raw_connect",
112            [CCS_MAC_SIGNAL]
113            = "ipc::signal",
114            [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CREATE]
115            = "capability::inet_tcp_create",
116            [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_LISTEN]
117            = "capability::inet_tcp_listen",
118            [CCS_MAX_MAC_INDEX + CCS_INET_STREAM_SOCKET_CONNECT]
119            = "capability::inet_tcp_connect",
120            [CCS_MAX_MAC_INDEX + CCS_USE_INET_DGRAM_SOCKET]
121            = "capability::use_inet_udp",
122            [CCS_MAX_MAC_INDEX + CCS_USE_INET_RAW_SOCKET]
123            = "capability::use_inet_ip",
124            [CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET]
125            = "capability::use_route",
126            [CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET]
127            = "capability::use_packet",
128            [CCS_MAX_MAC_INDEX + CCS_SYS_MOUNT]
129            = "capability::SYS_MOUNT",
130            [CCS_MAX_MAC_INDEX + CCS_SYS_UMOUNT]
131            = "capability::SYS_UMOUNT",
132            [CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT]
133            = "capability::SYS_REBOOT",
134            [CCS_MAX_MAC_INDEX + CCS_SYS_CHROOT]
135            = "capability::SYS_CHROOT",
136            [CCS_MAX_MAC_INDEX + CCS_SYS_KILL]
137            = "capability::SYS_KILL",
138            [CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP]
139            = "capability::SYS_VHANGUP",
140            [CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME]
141            = "capability::SYS_TIME",
142            [CCS_MAX_MAC_INDEX + CCS_SYS_NICE]
143            = "capability::SYS_NICE",
144            [CCS_MAX_MAC_INDEX + CCS_SYS_SETHOSTNAME]
145            = "capability::SYS_SETHOSTNAME",
146            [CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE]
147            = "capability::use_kernel_module",
148            [CCS_MAX_MAC_INDEX + CCS_CREATE_FIFO]
149            = "capability::create_fifo",
150            [CCS_MAX_MAC_INDEX + CCS_CREATE_BLOCK_DEV]
151            = "capability::create_block_dev",
152            [CCS_MAX_MAC_INDEX + CCS_CREATE_CHAR_DEV]
153            = "capability::create_char_dev",
154            [CCS_MAX_MAC_INDEX + CCS_CREATE_UNIX_SOCKET]
155            = "capability::create_unix_socket",
156            [CCS_MAX_MAC_INDEX + CCS_SYS_LINK]
157            = "capability::SYS_LINK",
158            [CCS_MAX_MAC_INDEX + CCS_SYS_SYMLINK]
159            = "capability::SYS_SYMLINK",
160            [CCS_MAX_MAC_INDEX + CCS_SYS_RENAME]
161            = "capability::SYS_RENAME",
162            [CCS_MAX_MAC_INDEX + CCS_SYS_UNLINK]
163            = "capability::SYS_UNLINK",
164            [CCS_MAX_MAC_INDEX + CCS_SYS_CHMOD]
165            = "capability::SYS_CHMOD",
166            [CCS_MAX_MAC_INDEX + CCS_SYS_CHOWN]
167            = "capability::SYS_CHOWN",
168            [CCS_MAX_MAC_INDEX + CCS_SYS_IOCTL]
169            = "capability::SYS_IOCTL",
170            [CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD]
171            = "capability::SYS_KEXEC_LOAD",
172            [CCS_MAX_MAC_INDEX + CCS_SYS_PIVOT_ROOT]
173            = "capability::SYS_PIVOT_ROOT",
174            [CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE]
175            = "capability::SYS_PTRACE",
176            [CCS_MAX_MAC_INDEX + CCS_CONCEAL_MOUNT]
177            = "capability::conceal_mount",
178            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
179             + CCS_MAC_CATEGORY_FILE] = "file",
180            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
181             + CCS_MAC_CATEGORY_NETWORK] = "network",
182            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
183             + CCS_MAC_CATEGORY_MISC] = "misc",
184            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
185             + CCS_MAC_CATEGORY_IPC] = "ipc",
186            [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
187             + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
188  };  };
189    
190  /* Permit policy management by non-root user? */  /* Permit policy management by non-root user? */
191  static bool ccs_manage_by_non_root;  static bool ccs_manage_by_non_root;
192    
193  /**  /**
194   * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.   * ccs_cap2keyword - Convert capability operation to capability name.
195   *   *
196   * @str: Unused.   * @operation: The capability index.
197   *   *
198   * Returns 0.   * Returns the name of the specified capability's name.
199   */   */
200  static int __init ccs_quiet_setup(char *str)  const char *ccs_cap2keyword(const u8 operation)
201  {  {
202          ccs_control_array[CCS_VERBOSE].current_value = 0;          return operation < CCS_MAX_CAPABILITY_INDEX
203          return 0;                  ? ccs_mac_keywords[CCS_MAX_MAC_INDEX + operation] + 12 : NULL;
204  }  }
205    
206  __setup("CCS_QUIET", ccs_quiet_setup);  /**
207     * ccs_yesno - Return "yes" or "no".
208     *
209     * @value: Bool value.
210     */
211    static const char *ccs_yesno(const unsigned int value)
212    {
213            return value ? "yes" : "no";
214    }
215    
216  /**  /**
217   * 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 247  bool ccs_io_printf(struct ccs_io_buffer
247   *   *
248   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
249   */   */
250  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
251                                                     profile)                                                            profile)
252  {  {
253          struct ccs_profile *ptr;          struct ccs_profile *ptr;
254          struct ccs_profile *entry;          struct ccs_profile *entry;
255          int i;          if (profile >= CCS_MAX_PROFILES)
         if (profile >= MAX_PROFILES)  
256                  return NULL;                  return NULL;
257          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
258          if (ptr)          if (ptr)
# Line 123  struct ccs_profile *ccs_find_or_assign_n Line 262  struct ccs_profile *ccs_find_or_assign_n
262          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
263          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
264                  ptr = entry;                  ptr = entry;
265                  for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)                  ptr->audit = &ccs_default_profile.preference;
266                          ptr->value[i] = ccs_control_array[i].current_value;                  ptr->learning = &ccs_default_profile.preference;
267                  /*                  ptr->permissive = &ccs_default_profile.preference;
268                   * Needn't to initialize "ptr->capability_value"                  ptr->enforcing = &ccs_default_profile.preference;
269                   * because they are always 0.                  ptr->default_config = CCS_CONFIG_DISABLED |
270                   */                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
271                    memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
272                           sizeof(ptr->config));
273                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
274                  ccs_profile_ptr[profile] = ptr;                  ccs_profile_ptr[profile] = ptr;
275                  entry = NULL;                  entry = NULL;
# Line 139  struct ccs_profile *ccs_find_or_assign_n Line 280  struct ccs_profile *ccs_find_or_assign_n
280  }  }
281    
282  /**  /**
283     * ccs_check_profile - Check all profiles currently assigned to domains are defined.
284     */
285    void ccs_check_profile(void)
286    {
287            struct ccs_domain_info *domain;
288            ccs_policy_loaded = true;
289            list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
290                    const u8 profile = domain->profile;
291                    if (ccs_profile_ptr[profile])
292                            continue;
293                    panic("Profile %u (used by '%s') not defined.\n",
294                          profile, domain->domainname->name);
295            }
296    }
297    
298    /**
299     * ccs_profile - Find a profile.
300     *
301     * @profile: Profile number to find.
302     *
303     * Returns pointer to "struct ccs_profile".
304     */
305    struct ccs_profile *ccs_profile(const u8 profile)
306    {
307            struct ccs_profile *ptr = ccs_profile_ptr[profile];
308            if (!ccs_policy_loaded)
309                    return &ccs_default_profile;
310            BUG_ON(!ptr);
311            return ptr;
312    }
313    
314    /**
315   * ccs_write_profile - Write profile table.   * ccs_write_profile - Write profile table.
316   *   *
317   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 149  static int ccs_write_profile(struct ccs_ Line 322  static int ccs_write_profile(struct ccs_
322  {  {
323          char *data = head->write_buf;          char *data = head->write_buf;
324          unsigned int i;          unsigned int i;
325          unsigned int value;          int value;
326            int mode;
327            u8 config;
328            bool use_default = false;
329          char *cp;          char *cp;
330          struct ccs_profile *ccs_profile;          struct ccs_profile *profile;
331          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
332          if (data != cp) {          if (data == cp) {
333                    profile = &ccs_default_profile;
334            } else {
335                  if (*cp != '-')                  if (*cp != '-')
336                          return -EINVAL;                          return -EINVAL;
337                  data = cp + 1;                  data = cp + 1;
338                    profile = ccs_find_or_assign_new_profile(i);
339                    if (!profile)
340                            return -EINVAL;
341          }          }
         ccs_profile = ccs_find_or_assign_new_profile(i);  
         if (!ccs_profile)  
                 return -EINVAL;  
342          cp = strchr(data, '=');          cp = strchr(data, '=');
343          if (!cp)          if (!cp)
344                  return -EINVAL;                  return -EINVAL;
345          *cp = '\0';          *cp++ = '\0';
346            if (profile != &ccs_default_profile)
347                    use_default = strstr(cp, "use_default") != NULL;
348            if (strstr(cp, "verbose=yes"))
349                    value = 1;
350            else if (strstr(cp, "verbose=no"))
351                    value = 0;
352            else
353                    value = -1;
354            if (!strcmp(data, "PREFERENCE::audit")) {
355    #ifdef CONFIG_CCSECURITY_AUDIT
356                    char *cp2;
357    #endif
358                    if (use_default) {
359                            profile->audit = &ccs_default_profile.preference;
360                            return 0;
361                    }
362                    profile->audit = &profile->preference;
363    #ifdef CONFIG_CCSECURITY_AUDIT
364                    cp2 = strstr(cp, "max_grant_log=");
365                    if (cp2)
366                            sscanf(cp2 + 14, "%u",
367                                   &profile->preference.audit_max_grant_log);
368                    cp2 = strstr(cp, "max_reject_log=");
369                    if (cp2)
370                            sscanf(cp2 + 15, "%u",
371                                   &profile->preference.audit_max_reject_log);
372    #endif
373                    if (strstr(cp, "task_info=yes"))
374                            profile->preference.audit_task_info = true;
375                    else if (strstr(cp, "task_info=no"))
376                            profile->preference.audit_task_info = false;
377                    if (strstr(cp, "path_info=yes"))
378                            profile->preference.audit_path_info = true;
379                    else if (strstr(cp, "path_info=no"))
380                            profile->preference.audit_path_info = false;
381                    return 0;
382            }
383            if (!strcmp(data, "PREFERENCE::enforcing")) {
384                    char *cp2;
385                    if (use_default) {
386                            profile->enforcing = &ccs_default_profile.preference;
387                            return 0;
388                    }
389                    profile->enforcing = &profile->preference;
390                    if (value >= 0)
391                            profile->preference.enforcing_verbose = value;
392                    cp2 = strstr(cp, "penalty=");
393                    if (cp2)
394                            sscanf(cp2 + 8, "%u",
395                                   &profile->preference.enforcing_penalty);
396                    return 0;
397            }
398            if (!strcmp(data, "PREFERENCE::permissive")) {
399                    if (use_default) {
400                            profile->permissive = &ccs_default_profile.preference;
401                            return 0;
402                    }
403                    profile->permissive = &profile->preference;
404                    if (value >= 0)
405                            profile->preference.permissive_verbose = value;
406                    return 0;
407            }
408            if (!strcmp(data, "PREFERENCE::learning")) {
409                    char *cp2;
410                    if (use_default) {
411                            profile->learning = &ccs_default_profile.preference;
412                            return 0;
413                    }
414                    profile->learning = &profile->preference;
415                    if (value >= 0)
416                            profile->preference.learning_verbose = value;
417                    cp2 = strstr(cp, "max_entry=");
418                    if (cp2)
419                            sscanf(cp2 + 10, "%u",
420                                   &profile->preference.learning_max_entry);
421                    if (strstr(cp, "exec.realpath=yes"))
422                            profile->preference.learning_exec_realpath = true;
423                    else if (strstr(cp, "exec.realpath=no"))
424                            profile->preference.learning_exec_realpath = false;
425                    if (strstr(cp, "exec.argv0=yes"))
426                            profile->preference.learning_exec_argv0 = true;
427                    else if (strstr(cp, "exec.argv0=no"))
428                            profile->preference.learning_exec_argv0 = false;
429                    if (strstr(cp, "symlink.target=yes"))
430                            profile->preference.learning_symlink_target = true;
431                    else if (strstr(cp, "symlink.target=no"))
432                            profile->preference.learning_symlink_target = false;
433                    return 0;
434            }
435            if (profile == &ccs_default_profile)
436                    return -EINVAL;
437          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
438                  const struct ccs_path_info *new_comment                  const struct ccs_path_info *old_comment = profile->comment;
439                          = ccs_get_name(cp + 1);                  profile->comment = ccs_get_name(cp);
                 const struct ccs_path_info *old_comment;  
                 /* Protect reader from ccs_put_name(). */  
                 /***** CRITICAL SECTION START *****/  
                 spin_lock(&ccs_profile_comment_lock);  
                 old_comment = ccs_profile->comment;  
                 ccs_profile->comment = new_comment;  
                 spin_unlock(&ccs_profile_comment_lock);  
                 /***** CRITICAL SECTION END *****/  
440                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
                 ccs_profile_entry_used[0] = true;  
441                  return 0;                  return 0;
442          }          }
443          if (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) {          if (!strcmp(data, "CONFIG")) {
444                  if (sscanf(cp + 1, "%u", &value) != 1) {                  i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
445                          for (i = 0; i < 4; i++) {                          + CCS_MAX_MAC_CATEGORY_INDEX;
446                                  if (strcmp(cp + 1, ccs_mode_4[i]))                  config = profile->default_config;
447                                          continue;          } else if (ccs_str_starts(&data, "CONFIG::")) {
448                                  value = i;                  config = 0;
449                                  break;                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
450                          }                               + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
451                          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]))  
452                                  continue;                                  continue;
453                          ccs_profile->capability_value[i] = value;                          config = profile->config[i];
454                          ccs_profile_entry_used[i + 1 + CCS_MAX_CONTROL_INDEX]                          break;
                                 = true;  
                         return 0;  
455                  }                  }
456                    if (i == CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
457                        + CCS_MAX_MAC_CATEGORY_INDEX)
458                            return -EINVAL;
459            } else {
460                  return -EINVAL;                  return -EINVAL;
461          }          }
462          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {          if (use_default) {
463                  if (strcmp(data, ccs_control_array[i].keyword))                  config = CCS_CONFIG_USE_DEFAULT;
464                          continue;          } else {
465                  if (sscanf(cp + 1, "%u", &value) != 1) {                  for (mode = 3; mode >= 0; mode--)
466                          int j;                          if (strstr(cp, ccs_mode_4[mode]))
467                          const char **modes;                                  /*
468                          switch (i) {                                   * Update lower 3 bits in order to distinguish
469                          case CCS_RESTRICT_AUTOBIND:                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
470                          case CCS_VERBOSE:                                   */
471                                  modes = ccs_mode_2;                                  config = (config & ~7) | mode;
472                                  break;  #ifdef CONFIG_CCSECURITY_AUDIT
473                          default:                  if (config != CCS_CONFIG_USE_DEFAULT) {
474                                  modes = ccs_mode_4;                          if (strstr(cp, "grant_log=yes"))
475                                  break;                                  config |= CCS_CONFIG_WANT_GRANT_LOG;
476                          }                          else if (strstr(cp, "grant_log=no"))
477                          for (j = 0; j < 4; j++) {                                  config &= ~CCS_CONFIG_WANT_GRANT_LOG;
478                                  if (strcmp(cp + 1, modes[j]))                          if (strstr(cp, "reject_log=yes"))
479                                          continue;                                  config |= CCS_CONFIG_WANT_REJECT_LOG;
480                                  value = j;                          else if (strstr(cp, "reject_log=no"))
481                                  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;  
482                  }                  }
483                  ccs_profile->value[i] = value;  #endif
                 ccs_profile_entry_used[i + 1] = true;  
                 return 0;  
484          }          }
485          return -EINVAL;          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
486                + CCS_MAX_MAC_CATEGORY_INDEX)
487                    profile->config[i] = config;
488            else if (config != CCS_CONFIG_USE_DEFAULT)
489                    profile->default_config = config;
490            return 0;
491  }  }
492    
493  /**  /**
494   * ccs_read_profile - Read profile table.   * ccs_read_profile - Read profile table.
495   *   *
496   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns 0.  
497   */   */
498  static int ccs_read_profile(struct ccs_io_buffer *head)  static void ccs_read_profile(struct ccs_io_buffer *head)
499  {  {
500          static const int ccs_total          int index;
                 = CCS_MAX_CONTROL_INDEX + CCS_MAX_CAPABILITY_INDEX + 1;  
         int step;  
501          if (head->read_eof)          if (head->read_eof)
502                  return 0;                  return;
503          for (step = head->read_step; step < MAX_PROFILES * ccs_total; step++) {          if (head->read_bit)
504                  const u8 index = step / ccs_total;                  goto body;
505                  u8 type = step % ccs_total;          ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
506                  const struct ccs_profile *ccs_profile = ccs_profile_ptr[index];          ccs_io_printf(head, "PREFERENCE::audit={ "
507                  head->read_step = step;  #ifdef CONFIG_CCSECURITY_AUDIT
508                  if (!ccs_profile)                        "max_grant_log=%u max_reject_log=%u "
509                          continue;  #endif
510                  if (!ccs_profile_entry_used[type])                        "task_info=%s path_info=%s }\n",
511                          continue;  #ifdef CONFIG_CCSECURITY_AUDIT
512                  if (!type) { /* Print profile' comment tag. */                        ccs_default_profile.preference.audit_max_grant_log,
513                          bool done;                        ccs_default_profile.preference.audit_max_reject_log,
514                          /***** CRITICAL SECTION START *****/  #endif
515                          spin_lock(&ccs_profile_comment_lock);                        ccs_yesno(ccs_default_profile.preference.
516                          done = ccs_io_printf(head, "%u-COMMENT=%s\n",                                  audit_task_info),
517                                               index, ccs_profile->comment ?                        ccs_yesno(ccs_default_profile.preference.
518                                               ccs_profile->comment->name : "");                                  audit_path_info));
519                          spin_unlock(&ccs_profile_comment_lock);          ccs_io_printf(head, "PREFERENCE::learning={ verbose=%s max_entry=%u "
520                          /***** CRITICAL SECTION END *****/                        "exec.realpath=%s exec.argv0=%s symlink.target=%s }\n",
521                          if (!done)                        ccs_yesno(ccs_default_profile.preference.
522                                  break;                                  learning_verbose),
523                          ccs_default_profile.preference.learning_max_entry,
524                          ccs_yesno(ccs_default_profile.preference.
525                                    learning_exec_realpath),
526                          ccs_yesno(ccs_default_profile.preference.
527                                    learning_exec_argv0),
528                          ccs_yesno(ccs_default_profile.preference.
529                                    learning_symlink_target));
530            ccs_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n",
531                          ccs_yesno(ccs_default_profile.preference.
532                                    permissive_verbose));
533            ccs_io_printf(head, "PREFERENCE::enforcing={ verbose=%s penalty=%u "
534                          "}\n",
535                          ccs_yesno(ccs_default_profile.preference.
536                                    enforcing_verbose),
537                          ccs_default_profile.preference.enforcing_penalty);
538            head->read_bit = 1;
539     body:
540            for (index = head->read_step; index < CCS_MAX_PROFILES; index++) {
541                    bool done;
542                    u8 config;
543                    int i;
544                    int pos;
545                    const struct ccs_profile *profile = ccs_profile_ptr[index];
546                    const struct ccs_path_info *comment;
547                    head->read_step = index;
548                    if (!profile)
549                          continue;                          continue;
550                    pos = head->read_avail;
551                    comment = profile->comment;
552                    done = ccs_io_printf(head, "%u-COMMENT=%s\n", index,
553                                         comment ? comment->name : "");
554                    if (!done)
555                            goto out;
556                    config = profile->default_config;
557    #ifdef CONFIG_CCSECURITY_AUDIT
558                    if (!ccs_io_printf(head, "%u-CONFIG={ mode=%s grant_log=%s "
559                                       "reject_log=%s }\n", index,
560                                       ccs_mode_4[config & 3],
561                                       ccs_yesno(config &
562                                                 CCS_CONFIG_WANT_GRANT_LOG),
563                                       ccs_yesno(config &
564                                                 CCS_CONFIG_WANT_REJECT_LOG)))
565                            goto out;
566    #else
567                    if (!ccs_io_printf(head, "%u-CONFIG={ mode=%s }\n", index,
568                                       ccs_mode_4[config & 3]))
569                            goto out;
570    #endif
571                    for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
572                                 + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
573    #ifdef CONFIG_CCSECURITY_AUDIT
574                            const char *g;
575                            const char *r;
576    #endif
577                            config = profile->config[i];
578                            if (config == CCS_CONFIG_USE_DEFAULT)
579                                    continue;
580    #ifdef CONFIG_CCSECURITY_AUDIT
581                            g = ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG);
582                            r = ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG);
583                            if (!ccs_io_printf(head, "%u-CONFIG::%s={ mode=%s "
584                                               "grant_log=%s reject_log=%s }\n",
585                                               index, ccs_mac_keywords[i],
586                                               ccs_mode_4[config & 3], g, r))
587                                    goto out;
588    #else
589                            if (!ccs_io_printf(head, "%u-CONFIG::%s={ mode=%s }\n",
590                                               index, ccs_mac_keywords[i],
591                                               ccs_mode_4[config & 3]))
592                                    goto out;
593    #endif
594                  }                  }
595                  type--;                  if (profile->audit != &ccs_default_profile.preference &&
596                  if (type >= CCS_MAX_CONTROL_INDEX) {                      !ccs_io_printf(head, "%u-PREFERENCE::audit={ "
597                          const int i = type - CCS_MAX_CONTROL_INDEX;  #ifdef CONFIG_CCSECURITY_AUDIT
598                          const u8 value = ccs_profile->capability_value[i];                                     "max_grant_log=%u max_reject_log=%u "
599                          if (!ccs_io_printf(head,  #endif
600                                             "%u-" KEYWORD_MAC_FOR_CAPABILITY                                     "task_info=%s path_info=%s }\n", index,
601                                             "%s=%s\n", index,  #ifdef CONFIG_CCSECURITY_AUDIT
602                                             ccs_capability_control_keyword[i],                                     profile->preference.audit_max_grant_log,
603                                             ccs_mode_4[value]))                                     profile->preference.audit_max_reject_log,
604                                  break;  #endif
605                  } else {                                     ccs_yesno(profile->preference.
606                          const unsigned int value = ccs_profile->value[type];                                               audit_task_info),
607                          const char **modes = NULL;                                     ccs_yesno(profile->preference.
608                          const char *keyword = ccs_control_array[type].keyword;                                               audit_path_info)))
609                          switch (ccs_control_array[type].max_value) {                          goto out;
610                          case 3:                  if (profile->learning != &ccs_default_profile.preference &&
611                                  modes = ccs_mode_4;                      !ccs_io_printf(head, "%u-PREFERENCE::learning={ "
612                                  break;                                     "verbose=%s max_entry=%u exec.realpath=%s "
613                          case 1:                                     "exec.argv0=%s symlink.target=%s }\n",
614                                  modes = ccs_mode_2;                                     index,
615                                  break;                                     ccs_yesno(profile->preference.
616                          }                                               learning_verbose),
617                          if (modes) {                                     profile->preference.learning_max_entry,
618                                  if (!ccs_io_printf(head, "%u-%s=%s\n", index,                                     ccs_yesno(profile->preference.
619                                                     keyword, modes[value]))                                               learning_exec_realpath),
620                                          break;                                     ccs_yesno(profile->preference.
621                          } else {                                               learning_exec_argv0),
622                                  if (!ccs_io_printf(head, "%u-%s=%u\n", index,                                     ccs_yesno(profile->preference.
623                                                     keyword, value))                                               learning_symlink_target)))
624                                          break;                          goto out;
625                          }                  if (profile->permissive != &ccs_default_profile.preference &&
626                  }                      !ccs_io_printf(head, "%u-PREFERENCE::permissive={ "
627                                       "verbose=%s }\n", index,
628                                       ccs_yesno(profile->preference.
629                                                 permissive_verbose)))
630                            goto out;
631                    if (profile->enforcing != &ccs_default_profile.preference &&
632                        !ccs_io_printf(head, "%u-PREFERENCE::enforcing={ "
633                                       "verbose=%s penalty=%u }\n", index,
634                                       ccs_yesno(profile->preference.
635                                                 enforcing_verbose),
636                                       profile->preference.enforcing_penalty))
637                            goto out;
638                    continue;
639     out:
640                    head->read_avail = pos;
641                    break;
642          }          }
643          if (step == MAX_PROFILES * ccs_total)          if (index == CCS_MAX_PROFILES)
644                  head->read_eof = true;                  head->read_eof = true;
         return 0;  
645  }  }
646    
647  /* 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 659  static int ccs_update_manager_entry(cons
659  {  {
660          struct ccs_policy_manager_entry *entry = NULL;          struct ccs_policy_manager_entry *entry = NULL;
661          struct ccs_policy_manager_entry *ptr;          struct ccs_policy_manager_entry *ptr;
662          const struct ccs_path_info *saved_manager;          struct ccs_policy_manager_entry e = { };
663          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
         bool is_domain = false;  
664          if (ccs_is_domain_def(manager)) {          if (ccs_is_domain_def(manager)) {
665                  if (!ccs_is_correct_domain(manager))                  if (!ccs_is_correct_domain(manager))
666                          return -EINVAL;                          return -EINVAL;
667                  is_domain = true;                  e.is_domain = true;
668          } else {          } else {
669                  if (!ccs_is_correct_path(manager, 1, -1, -1))                  if (!ccs_is_correct_path(manager, 1, -1, -1))
670                          return -EINVAL;                          return -EINVAL;
671          }          }
672          saved_manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
673          if (!saved_manager)          if (!e.manager)
674                  return -ENOMEM;                  return -ENOMEM;
675          if (!is_delete)          if (!is_delete)
676                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);                  entry = kmalloc(sizeof(e), GFP_KERNEL);
677          mutex_lock(&ccs_policy_lock);          mutex_lock(&ccs_policy_lock);
678          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
679                  if (ptr->manager != saved_manager)                  if (ptr->manager != e.manager)
680                          continue;                          continue;
681                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
682                  error = 0;                  error = 0;
683                  break;                  break;
684          }          }
685          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;  
686                  list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);                  list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
687                  entry = NULL;                  entry = NULL;
688                  error = 0;                  error = 0;
689          }          }
690          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
691          ccs_put_name(saved_manager);          ccs_put_name(e.manager);
692          kfree(entry);          kfree(entry);
693          return error;          return error;
694  }  }
# Line 373  static int ccs_update_manager_entry(cons Line 703  static int ccs_update_manager_entry(cons
703  static int ccs_write_manager_policy(struct ccs_io_buffer *head)  static int ccs_write_manager_policy(struct ccs_io_buffer *head)
704  {  {
705          char *data = head->write_buf;          char *data = head->write_buf;
706          bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
707          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
708                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !is_delete;
709                  return 0;                  return 0;
# Line 386  static int ccs_write_manager_policy(stru Line 716  static int ccs_write_manager_policy(stru
716   *   *
717   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
718   *   *
  * Returns 0.  
  *  
719   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
720   */   */
721  static int ccs_read_manager_policy(struct ccs_io_buffer *head)  static void ccs_read_manager_policy(struct ccs_io_buffer *head)
722  {  {
723          struct list_head *pos;          struct list_head *pos;
         ccs_check_read_lock();  
724          if (head->read_eof)          if (head->read_eof)
725                  return 0;                  return;
726          list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {          list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
727                  struct ccs_policy_manager_entry *ptr;                  struct ccs_policy_manager_entry *ptr;
728                  ptr = list_entry(pos, struct ccs_policy_manager_entry, list);                  ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
729                  if (ptr->is_deleted)                  if (ptr->is_deleted)
730                          continue;                          continue;
731                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
732                          return 0;                          return;
733          }          }
734          head->read_eof = true;          head->read_eof = true;
         return 0;  
735  }  }
736    
737  /**  /**
# Line 424  static bool ccs_is_policy_manager(void) Line 750  static bool ccs_is_policy_manager(void)
750          const struct ccs_path_info *domainname          const struct ccs_path_info *domainname
751                  = ccs_current_domain()->domainname;                  = ccs_current_domain()->domainname;
752          bool found = false;          bool found = false;
         ccs_check_read_lock();  
753          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
754                  return true;                  return true;
755          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 830  static bool ccs_is_select_one(struct ccs
830  {  {
831          unsigned int pid;          unsigned int pid;
832          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
833          ccs_check_read_lock();          bool global_pid = false;
834          if (!strcmp(data, "allow_execute")) {          if (!strcmp(data, "allow_execute")) {
835                  head->read_execute_only = true;                  head->read_execute_only = true;
836                  return true;                  return true;
837          }          }
838          if (sscanf(data, "pid=%u", &pid) == 1) {          if (sscanf(data, "pid=%u", &pid) == 1 ||
839                (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
840                  struct task_struct *p;                  struct task_struct *p;
                 /***** CRITICAL SECTION START *****/  
841                  read_lock(&tasklist_lock);                  read_lock(&tasklist_lock);
842    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
843                    if (global_pid)
844                            p = find_task_by_pid_ns(pid, &init_pid_ns);
845                    else
846                            p = find_task_by_vpid(pid);
847    #else
848                  p = find_task_by_pid(pid);                  p = find_task_by_pid(pid);
849    #endif
850                  if (p)                  if (p)
851                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
852                  read_unlock(&tasklist_lock);                  read_unlock(&tasklist_lock);
                 /***** CRITICAL SECTION END *****/  
853          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
854                  if (ccs_is_domain_def(data + 7))                  if (ccs_is_domain_def(data + 7))
855                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
# Line 549  static bool ccs_is_select_one(struct ccs Line 880  static bool ccs_is_select_one(struct ccs
880          return true;          return true;
881  }  }
882    
883    static int ccs_write_domain_policy2(char *data, struct ccs_domain_info *domain,
884                                        struct ccs_condition *cond,
885                                        const bool is_delete)
886    {
887            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))
888                    return ccs_write_capability_policy(data, domain, cond,
889                                                       is_delete);
890            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))
891                    return ccs_write_network_policy(data, domain, cond, is_delete);
892            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))
893                    return ccs_write_signal_policy(data, domain, cond, is_delete);
894            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
895                    return ccs_write_env_policy(data, domain, cond, is_delete);
896            if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))
897                    return ccs_write_mount_policy(data, domain, cond, is_delete);
898            return ccs_write_file_policy(data, domain, cond, is_delete);
899    }
900    
901  /**  /**
902   * ccs_write_domain_policy - Write domain policy.   * ccs_write_domain_policy - Write domain policy.
903   *   *
# Line 566  static int ccs_write_domain_policy(struc Line 915  static int ccs_write_domain_policy(struc
915          struct ccs_condition *cond = NULL;          struct ccs_condition *cond = NULL;
916          char *cp;          char *cp;
917          int error;          int error;
918          if (ccs_str_starts(&data, KEYWORD_DELETE))          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
919                  is_delete = true;                  is_delete = true;
920          else if (ccs_str_starts(&data, KEYWORD_SELECT))          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
921                  is_select = true;                  is_select = true;
922          if (is_select && ccs_is_select_one(head, data))          if (is_select && ccs_is_select_one(head, data))
923                  return 0;                  return 0;
# Line 589  static int ccs_write_domain_policy(struc Line 938  static int ccs_write_domain_policy(struc
938          if (!domain)          if (!domain)
939                  return -EINVAL;                  return -EINVAL;
940    
941          if (sscanf(data, KEYWORD_USE_PROFILE "%u", &profile) == 1          if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1
942              && profile < MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
943                  if (ccs_profile_ptr[profile] || !ccs_policy_loaded)                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])
944                          domain->profile = (u8) profile;                          domain->profile = (u8) profile;
945                  return 0;                  return 0;
946          }          }
947          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
948                  domain->ignore_global_allow_read = !is_delete;                  domain->ignore_global_allow_read = !is_delete;
949                  return 0;                  return 0;
950          }          }
951          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
952                  domain->ignore_global_allow_env = !is_delete;                  domain->ignore_global_allow_env = !is_delete;
953                  return 0;                  return 0;
954          }          }
# Line 609  static int ccs_write_domain_policy(struc Line 958  static int ccs_write_domain_policy(struc
958                  if (!cond)                  if (!cond)
959                          return -EINVAL;                          return -EINVAL;
960          }          }
961          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);  
962          if (cond)          if (cond)
963                  ccs_put_condition(cond);                  ccs_put_condition(cond);
964          return error;          return error;
965  }  }
966    
967    /**
968     * ccs_print_name_union - Print a ccs_name_union.
969     *
970     * @head: Pointer to "struct ccs_io_buffer".
971     * @ptr:  Pointer to "struct ccs_name_union".
972     *
973     * Returns true on success, false otherwise.
974     */
975  static bool ccs_print_name_union(struct ccs_io_buffer *head,  static bool ccs_print_name_union(struct ccs_io_buffer *head,
976                                   struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
977  {  {
978          const int pos = head->read_avail;          int pos = head->read_avail;
979          if (pos && head->read_buf[pos - 1] == ' ')          if (pos && head->read_buf[pos - 1] == ' ')
980                  head->read_avail--;                  head->read_avail--;
981          if (ptr->is_group)          if (ptr->is_group)
# Line 648  static bool ccs_print_name_union(struct Line 984  static bool ccs_print_name_union(struct
984          return ccs_io_printf(head, " %s", ptr->filename->name);          return ccs_io_printf(head, " %s", ptr->filename->name);
985  }  }
986    
987  static bool ccs_print_number_union(struct ccs_io_buffer *head,  /**
988                                     struct ccs_number_union *ptr)   * ccs_print_name_union_quoted - Print a ccs_name_union with double quotes.
989     *
990     * @head: Pointer to "struct ccs_io_buffer".
991     * @ptr:  Pointer to "struct ccs_name_union".
992     *
993     * Returns true on success, false otherwise.
994     */
995    static bool ccs_print_name_union_quoted(struct ccs_io_buffer *head,
996                                            const struct ccs_name_union *ptr)
997    {
998            if (ptr->is_group)
999                    return ccs_io_printf(head, "@%s",
1000                                         ptr->group->group_name->name);
1001            return ccs_io_printf(head, "\"%s\"", ptr->filename->name);
1002    }
1003    
1004    /**
1005     * ccs_print_number_union_common - Print a ccs_number_union.
1006     *
1007     * @head:       Pointer to "struct ccs_io_buffer".
1008     * @ptr:        Pointer to "struct ccs_number_union".
1009     * @need_space: True if a space character is needed.
1010     *
1011     * Returns true on success, false otherwise.
1012     */
1013    static bool ccs_print_number_union_common(struct ccs_io_buffer *head,
1014                                              const struct ccs_number_union *ptr,
1015                                              const bool need_space)
1016  {  {
1017          unsigned long min;          unsigned long min;
1018          unsigned long max;          unsigned long max;
1019            u8 min_type;
1020            u8 max_type;
1021            if (need_space && !ccs_io_printf(head, " "))
1022                    return false;
1023          if (ptr->is_group)          if (ptr->is_group)
1024                  return ccs_io_printf(head, " @%s",                  return ccs_io_printf(head, "@%s",
1025                                       ptr->group->group_name->name);                                       ptr->group->group_name->name);
1026            min_type = ptr->min_type;
1027            max_type = ptr->max_type;
1028          min = ptr->values[0];          min = ptr->values[0];
1029          max = ptr->values[1];          max = ptr->values[1];
1030          if (min == max)          switch (min_type) {
1031                  return ccs_io_printf(head, " %lu", min);          case CCS_VALUE_TYPE_HEXADECIMAL:
1032          return ccs_io_printf(head, " %lu-%lu", min, max);                  if (!ccs_io_printf(head, "0x%lX", min))
1033                            return false;
1034                    break;
1035            case CCS_VALUE_TYPE_OCTAL:
1036                    if (!ccs_io_printf(head, "0%lo", min))
1037                            return false;
1038                    break;
1039            default:
1040                    if (!ccs_io_printf(head, "%lu", min))
1041                            return false;
1042                    break;
1043            }
1044            if (min == max && min_type == max_type)
1045                    return true;
1046            switch (max_type) {
1047            case CCS_VALUE_TYPE_HEXADECIMAL:
1048                    return ccs_io_printf(head, "-0x%lX", max);
1049            case CCS_VALUE_TYPE_OCTAL:
1050                    return ccs_io_printf(head, "-0%lo", max);
1051            default:
1052                    return ccs_io_printf(head, "-%lu", max);
1053            }
1054    }
1055    
1056    /**
1057     * ccs_print_number_union - Print a ccs_number_union.
1058     *
1059     * @head:       Pointer to "struct ccs_io_buffer".
1060     * @ptr:        Pointer to "struct ccs_number_union".
1061     *
1062     * Returns true on success, false otherwise.
1063     */
1064    bool ccs_print_number_union(struct ccs_io_buffer *head,
1065                                const struct ccs_number_union *ptr)
1066    {
1067            return ccs_print_number_union_common(head, ptr, true);
1068  }  }
1069    
1070  /**  /**
1071   * ccs_print_single_path_acl - Print a single path ACL entry.   * ccs_print_number_union_nospace - Print a ccs_number_union without a space character.
1072     *
1073     * @head:       Pointer to "struct ccs_io_buffer".
1074     * @ptr:        Pointer to "struct ccs_number_union".
1075     *
1076     * Returns true on success, false otherwise.
1077     */
1078    static bool ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1079                                               const struct ccs_number_union *ptr)
1080    {
1081            return ccs_print_number_union_common(head, ptr, false);
1082    }
1083    
1084    /**
1085     * ccs_print_condition - Print condition part.
1086   *   *
1087   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  * @ptr:  Pointer to "struct ccs_single_path_acl_record".  
1088   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1089   *   *
1090   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1091   */   */
1092  static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_condition(struct ccs_io_buffer *head,
1093                                        struct ccs_single_path_acl_record *ptr,                                  const struct ccs_condition *cond)
1094                                        const struct ccs_condition *cond)  {
1095            const struct ccs_condition_element *condp;
1096            const struct ccs_number_union *numbers_p;
1097            const struct ccs_name_union *names_p;
1098            const struct ccs_argv_entry *argv;
1099            const struct ccs_envp_entry *envp;
1100            u16 condc;
1101            u16 i;
1102            u16 j;
1103            char buffer[32];
1104            if (!cond)
1105                    goto no_condition;
1106            condc = cond->condc;
1107            condp = (const struct ccs_condition_element *) (cond + 1);
1108            numbers_p = (const struct ccs_number_union *) (condp + condc);
1109            names_p = (const struct ccs_name_union *)
1110                    (numbers_p + cond->numbers_count);
1111            argv = (const struct ccs_argv_entry *) (names_p + cond->names_count);
1112            envp = (const struct ccs_envp_entry *) (argv + cond->argc);
1113            memset(buffer, 0, sizeof(buffer));
1114            if (condc && !ccs_io_printf(head, "%s", " if"))
1115                    goto out;
1116            for (i = 0; i < condc; i++) {
1117                    const u8 match = condp->equals;
1118                    const u8 left = condp->left;
1119                    const u8 right = condp->right;
1120                    condp++;
1121                    switch (left) {
1122                    case CCS_ARGV_ENTRY:
1123                            if (!ccs_io_printf(head, " exec.argv[%u]%s\"%s\"",
1124                                               argv->index, argv->is_not ?
1125                                               "!=" : "=", argv->value->name))
1126                                    goto out;
1127                            argv++;
1128                            continue;
1129                    case CCS_ENVP_ENTRY:
1130                            if (!ccs_io_printf(head, " exec.envp[\"%s\"]%s",
1131                                               envp->name->name, envp->is_not ?
1132                                               "!=" : "="))
1133                                    goto out;
1134                            if (envp->value) {
1135                                    if (!ccs_io_printf(head, "\"%s\"",
1136                                                       envp->value->name))
1137                                            goto out;
1138                            } else {
1139                                    if (!ccs_io_printf(head, "NULL"))
1140                                            goto out;
1141                            }
1142                            envp++;
1143                            continue;
1144                    case CCS_NUMBER_UNION:
1145                            if (!ccs_print_number_union(head, numbers_p++))
1146                                    goto out;
1147                            break;
1148                    default:
1149                            if (left >= CCS_MAX_CONDITION_KEYWORD)
1150                                    goto out;
1151                            if (!ccs_io_printf(head, " %s",
1152                                               ccs_condition_keyword[left]))
1153                                    goto out;
1154                            break;
1155                    }
1156                    if (!ccs_io_printf(head, "%s", match ? "=" : "!="))
1157                            goto out;
1158                    switch (right) {
1159                    case CCS_NAME_UNION:
1160                            if (!ccs_print_name_union_quoted(head, names_p++))
1161                                    goto out;
1162                            break;
1163                    case CCS_NUMBER_UNION:
1164                            if (!ccs_print_number_union_nospace(head, numbers_p++))
1165                                    goto out;
1166                            break;
1167                    default:
1168                            if (right >= CCS_MAX_CONDITION_KEYWORD)
1169                                    goto out;
1170                            if (!ccs_io_printf(head, "%s",
1171                                               ccs_condition_keyword[right]))
1172                                    goto out;
1173                            break;
1174                    }
1175            }
1176            i = cond->post_state[3];
1177            if (!i)
1178                    goto no_condition;
1179            if (!ccs_io_printf(head, " ; set"))
1180                    goto out;
1181            for (j = 0; j < 3; j++) {
1182                    if (!(i & (1 << j)))
1183                            continue;
1184                    if (!ccs_io_printf(head, " task.state[%u]=%u", j,
1185                                       cond->post_state[j]))
1186                            goto out;
1187            }
1188     no_condition:
1189            if (ccs_io_printf(head, "\n"))
1190                    return true;
1191     out:
1192            return false;
1193    }
1194    
1195    /**
1196     * ccs_print_path_acl - Print a path ACL entry.
1197     *
1198     * @head: Pointer to "struct ccs_io_buffer".
1199     * @ptr:  Pointer to "struct ccs_path_acl".
1200     * @cond: Pointer to "struct ccs_condition". May be NULL.
1201     *
1202     * Returns true on success, false otherwise.
1203     */
1204    static bool ccs_print_path_acl(struct ccs_io_buffer *head,
1205                                   struct ccs_path_acl *ptr,
1206                                   const struct ccs_condition *cond)
1207  {  {
1208          int pos;          int pos;
1209          u8 bit;          u8 bit;
1210          const u16 perm = ptr->perm;          const u16 perm = ptr->perm;
1211          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;  
1212                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1213                          continue;                          continue;
1214                  if (head->read_execute_only && bit != TYPE_EXECUTE_ACL)                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE)
1215                          continue;                          continue;
1216                  /* Print "read/write" instead of "read" and "write". */                  /* Print "read/write" instead of "read" and "write". */
1217                  if ((bit == TYPE_READ_ACL || bit == TYPE_WRITE_ACL)                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
1218                      && (perm & (1 << TYPE_READ_WRITE_ACL)))                      && (perm & (1 << CCS_TYPE_READ_WRITE)))
1219                          continue;                          continue;
                 msg = ccs_sp2keyword(bit);  
1220                  pos = head->read_avail;                  pos = head->read_avail;
1221                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||
1222                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1223                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
1224                          goto out;                          head->read_bit = bit;
1225                            head->read_avail = pos;
1226                            return false;
1227                    }
1228          }          }
1229          head->read_bit = 0;          head->read_bit = 0;
1230          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
1231  }  }
1232    
1233  /**  /**
1234   * ccs_print_mkdev_acl - Print a mkdev ACL entry.   * ccs_print_path_number3_acl - Print a path_number3 ACL entry.
1235   *   *
1236   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1237   * @ptr:  Pointer to "struct ccs_mkdev_acl_record".   * @ptr:  Pointer to "struct ccs_path_number3_acl".
1238   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1239   *   *
1240   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1241   */   */
1242  static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number3_acl(struct ccs_io_buffer *head,
1243                                  struct ccs_mkdev_acl_record *ptr,                                         struct ccs_path_number3_acl *ptr,
1244                                  const struct ccs_condition *cond)                                         const struct ccs_condition *cond)
1245  {  {
1246          int pos;          int pos;
1247          u8 bit;          u8 bit;
1248          const u16 perm = ptr->perm;          const u16 perm = ptr->perm;
1249          for (bit = head->read_bit; bit < MAX_MKDEV_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER3_OPERATION;
1250                  const char *msg;               bit++) {
1251                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1252                          continue;                          continue;
                 msg = ccs_mkdev2keyword(bit);  
1253                  pos = head->read_avail;                  pos = head->read_avail;
1254                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1255                                       ccs_path_number32keyword(bit)) ||
1256                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1257                        !ccs_print_number_union(head, &ptr->mode) ||
1258                      !ccs_print_number_union(head, &ptr->major) ||                      !ccs_print_number_union(head, &ptr->major) ||
1259                      !ccs_print_number_union(head, &ptr->minor) ||                      !ccs_print_number_union(head, &ptr->minor) ||
1260                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
1261                          goto out;                          head->read_bit = bit;
1262                            head->read_avail = pos;
1263                            return false;
1264                    }
1265          }          }
1266          head->read_bit = 0;          head->read_bit = 0;
1267          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
1268  }  }
1269    
1270  /**  /**
1271   * ccs_print_double_path_acl - Print a double path ACL entry.   * ccs_print_path2_acl - Print a path2 ACL entry.
1272   *   *
1273   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1274   * @ptr:  Pointer to "struct ccs_double_path_acl_record".   * @ptr:  Pointer to "struct ccs_path2_acl".
1275   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1276   *   *
1277   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1278   */   */
1279  static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_path2_acl(struct ccs_io_buffer *head,
1280                                        struct ccs_double_path_acl_record *ptr,                                  struct ccs_path2_acl *ptr,
1281                                        const struct ccs_condition *cond)                                  const struct ccs_condition *cond)
1282  {  {
1283          int pos;          int pos;
1284          u8 bit;          u8 bit;
1285          const u8 perm = ptr->perm;          const u8 perm = ptr->perm;
1286          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;  
1287                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1288                          continue;                          continue;
                 msg = ccs_dp2keyword(bit);  
1289                  pos = head->read_avail;                  pos = head->read_avail;
1290                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1291                                       ccs_path22keyword(bit)) ||
1292                      !ccs_print_name_union(head, &ptr->name1) ||                      !ccs_print_name_union(head, &ptr->name1) ||
1293                      !ccs_print_name_union(head, &ptr->name2) ||                      !ccs_print_name_union(head, &ptr->name2) ||
1294                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
1295                          goto out;                          head->read_bit = bit;
1296                            head->read_avail = pos;
1297                            return false;
1298                    }
1299          }          }
1300          head->read_bit = 0;          head->read_bit = 0;
1301          return true;          return true;
  out:  
         head->read_bit = bit;  
         head->read_avail = pos;  
         return false;  
1302  }  }
1303    
1304  /**  /**
1305   * ccs_print_path_number_acl - Print an ioctl/chmod/chown/chgrp ACL entry.   * ccs_print_path_number_acl - Print a path_number ACL entry.
1306   *   *
1307   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1308   * @ptr:  Pointer to "struct ccs_path_number_acl_record".   * @ptr:  Pointer to "struct ccs_path_number_acl".
1309   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1310   *   *
1311   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1312   */   */
1313  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
1314                                        struct ccs_path_number_acl_record *ptr,                                        struct ccs_path_number_acl *ptr,
1315                                        const struct ccs_condition *cond)                                        const struct ccs_condition *cond)
1316  {  {
1317          int pos;          int pos;
1318          u8 bit;          u8 bit;
1319          const u8 perm = ptr->perm;          const u8 perm = ptr->perm;
1320          for (bit = head->read_bit; bit < MAX_PATH_NUMBER_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION;
1321                  const char *msg;               bit++) {
1322                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1323                          continue;                          continue;
                 msg = ccs_path_number2keyword(bit);  
1324                  pos = head->read_avail;                  pos = head->read_avail;
1325                  if (!ccs_io_printf(head, "allow_%s", msg) ||                  if (!ccs_io_printf(head, "allow_%s",
1326                                       ccs_path_number2keyword(bit)) ||
1327                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1328                      !ccs_print_number_union(head, &ptr->number) ||                      !ccs_print_number_union(head, &ptr->number) ||
1329                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond)) {
1330                          goto out;                          head->read_bit = bit;
1331                            head->read_avail = pos;
1332                            return false;
1333                    }
1334          }          }
1335          head->read_bit = 0;          head->read_bit = 0;
1336          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;  
1337  }  }
1338    
1339  /**  /**
1340   * ccs_print_env_acl - Print an evironment variable name's ACL entry.   * ccs_print_env_acl - Print an evironment variable name's ACL entry.
1341   *   *
1342   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1343   * @ptr:  Pointer to "struct ccs_env_acl_record".   * @ptr:  Pointer to "struct ccs_env_acl".
1344   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1345   *   *
1346   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1347   */   */
1348  static bool ccs_print_env_acl(struct ccs_io_buffer *head,  static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1349                                struct ccs_env_acl_record *ptr,                                struct ccs_env_acl *ptr,
1350                                const struct ccs_condition *cond)                                const struct ccs_condition *cond)
1351  {  {
1352          int pos = head->read_avail;          const int pos = head->read_avail;
1353          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) ||
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_capability_acl - Print a capability ACL entry.   * ccs_print_capability_acl - Print a capability ACL entry.
1363   *   *
1364   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1365   * @ptr:  Pointer to "struct ccs_capability_acl_record".   * @ptr:  Pointer to "struct ccs_capability_acl".
1366   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1367   *   *
1368   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1369   */   */
1370  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1371                                       struct ccs_capability_acl_record *ptr,                                       struct ccs_capability_acl *ptr,
1372                                       const struct ccs_condition *cond)                                       const struct ccs_condition *cond)
1373  {  {
1374          int pos = head->read_avail;          const int pos = head->read_avail;
1375          if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1376                             ccs_cap2keyword(ptr->operation)))                             ccs_cap2keyword(ptr->operation)) ||
1377                  goto out;              !ccs_print_condition(head, cond)) {
1378          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1379                  goto out;                  return false;
1380            }
1381          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1382  }  }
1383    
1384  /**  /**
1385   * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.   * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.
1386   *   *
1387   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1388   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1389   *   *
1390   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1391   */   */
1392  static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,  static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,
1393                                   struct ccs_ip_network_acl_record *ptr)                                   struct ccs_ip_network_acl *ptr)
1394  {  {
1395          const u32 min_address = ptr->address.ipv4.min;          const u32 min_address = ptr->address.ipv4.min;
1396          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 1406  static bool ccs_print_ipv4_entry(struct
1406   * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.   * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.
1407   *   *
1408   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1409   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1410   *   *
1411   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1412   */   */
1413  static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,  static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,
1414                                   struct ccs_ip_network_acl_record *ptr)                                   struct ccs_ip_network_acl *ptr)
1415  {  {
1416          char buf[64];          char buf[64];
1417          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 1431  static bool ccs_print_ipv6_entry(struct
1431   * ccs_print_network_acl - Print a network ACL entry.   * ccs_print_network_acl - Print a network ACL entry.
1432   *   *
1433   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1434   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
1435   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1436   *   *
1437   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1438   */   */
1439  static bool ccs_print_network_acl(struct ccs_io_buffer *head,  static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1440                                    struct ccs_ip_network_acl_record *ptr,                                    struct ccs_ip_network_acl *ptr,
1441                                    const struct ccs_condition *cond)                                    const struct ccs_condition *cond)
1442  {  {
1443          int pos = head->read_avail;          int pos;
1444          if (!ccs_io_printf(head, KEYWORD_ALLOW_NETWORK "%s ",          u8 bit;
1445                             ccs_net2keyword(ptr->operation_type)))          const u16 perm = ptr->perm;
1446                  goto out;          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1447          switch (ptr->record_type) {                  if (!(perm & (1 << bit)))
1448          case IP_RECORD_TYPE_ADDRESS_GROUP:                          continue;
1449                  if (!ccs_io_printf(head, "@%s",                  pos = head->read_avail;
1450                                     ptr->address.group->group_name->name))                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",
1451                          goto out;                                     ccs_net2keyword(bit)))
                 break;  
         case IP_RECORD_TYPE_IPv4:  
                 if (!ccs_print_ipv4_entry(head, ptr))  
1452                          goto out;                          goto out;
1453                  break;                  switch (ptr->address_type) {
1454          case IP_RECORD_TYPE_IPv6:                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1455                  if (!ccs_print_ipv6_entry(head, ptr))                          if (!ccs_io_printf(head, "@%s", ptr->address.group->
1456                                               group_name->name))
1457                                    goto out;
1458                            break;
1459                    case CCS_IP_ADDRESS_TYPE_IPv4:
1460                            if (!ccs_print_ipv4_entry(head, ptr))
1461                                    goto out;
1462                            break;
1463                    case CCS_IP_ADDRESS_TYPE_IPv6:
1464                            if (!ccs_print_ipv6_entry(head, ptr))
1465                                    goto out;
1466                            break;
1467                    }
1468                    if (!ccs_print_number_union(head, &ptr->port) ||
1469                        !ccs_print_condition(head, cond))
1470                          goto out;                          goto out;
                 break;  
1471          }          }
1472          if (!ccs_print_number_union(head, &ptr->port) ||          head->read_bit = 0;
             !ccs_print_condition(head, cond))  
                 goto out;  
1473          return true;          return true;
1474   out:   out:
1475            head->read_bit = bit;
1476          head->read_avail = pos;          head->read_avail = pos;
1477          return false;          return false;
1478  }  }
# Line 978  static bool ccs_print_network_acl(struct Line 1481  static bool ccs_print_network_acl(struct
1481   * ccs_print_signal_acl - Print a signal ACL entry.   * ccs_print_signal_acl - Print a signal ACL entry.
1482   *   *
1483   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1484   * @ptr:  Pointer to "struct signale_acl_record".   * @ptr:  Pointer to "struct signale_acl".
1485   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1486   *   *
1487   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1488   */   */
1489  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1490                                   struct ccs_signal_acl_record *ptr,                                   struct ccs_signal_acl *ptr,
1491                                   const struct ccs_condition *cond)                                   const struct ccs_condition *cond)
1492  {  {
1493          int pos = head->read_avail;          const int pos = head->read_avail;
1494          if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1495                             ptr->sig, ptr->domainname->name))                             ptr->sig, ptr->domainname->name) ||
1496                  goto out;              !ccs_print_condition(head, cond)) {
1497          if (!ccs_print_condition(head, cond))                  head->read_avail = pos;
1498                  goto out;                  return false;
1499            }
1500          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1501  }  }
1502    
1503  /**  /**
# Line 1020  static bool ccs_print_execute_handler_re Line 1521  static bool ccs_print_execute_handler_re
1521   * ccs_print_mount_acl - Print a mount ACL entry.   * ccs_print_mount_acl - Print a mount ACL entry.
1522   *   *
1523   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1524   * @ptr:  Pointer to "struct ccs_mount_acl_record".   * @ptr:  Pointer to "struct ccs_mount_acl".
1525   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1526   *   *
1527   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1528   */   */
1529  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1530                                  struct ccs_mount_acl_record *ptr,                                  struct ccs_mount_acl *ptr,
1531                                  const struct ccs_condition *cond)                                  const struct ccs_condition *cond)
1532  {  {
1533          int pos = head->read_avail;          const int pos = head->read_avail;
1534          if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
1535                             ptr->dev_name->name, ptr->dir_name->name,              !ccs_print_name_union(head, &ptr->dev_name) ||
1536                             ptr->fs_type->name, ptr->flags))              !ccs_print_name_union(head, &ptr->dir_name) ||
1537                  goto out;              !ccs_print_name_union(head, &ptr->fs_type) ||
1538          if (!ccs_print_condition(head, cond))              !ccs_print_number_union(head, &ptr->flags) ||
1539                  goto out;              !ccs_print_condition(head, cond)) {
1540          return true;                  head->read_avail = pos;
1541   out:                  return false;
1542          head->read_avail = pos;          }
         return false;  
 }  
   
 /**  
  * ccs_print_umount_acl - Print a mount ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_umount_acl_record".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_umount_acl(struct ccs_io_buffer *head,  
                                  struct ccs_umount_acl_record *ptr,  
                                  const struct ccs_condition *cond)  
 {  
         int pos = head->read_avail;  
         if (!ccs_io_printf(head, KEYWORD_ALLOW_UNMOUNT "%s\n",  
                            ptr->dir->name))  
                 goto out;  
         if (!ccs_print_condition(head, cond))  
                 goto out;  
         return true;  
  out:  
         head->read_avail = pos;  
         return false;  
 }  
   
 /**  
  * ccs_print_chroot_acl - Print a chroot ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_chroot_acl_record".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,  
                                  struct ccs_chroot_acl_record *ptr,  
                                  const struct ccs_condition *cond)  
 {  
         int pos = head->read_avail;  
         if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s\n",  
                            ptr->dir->name))  
                 goto out;  
         if (!ccs_print_condition(head, cond))  
                 goto out;  
         return true;  
  out:  
         head->read_avail = pos;  
         return false;  
 }  
   
 /**  
  * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_pivot_root_acl_record".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,  
                                      struct ccs_pivot_root_acl_record *ptr,  
                                      const struct ccs_condition *cond)  
 {  
         int pos = head->read_avail;  
         if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",  
                            ptr->new_root->name, ptr->old_root->name))  
                 goto out;  
         if (!ccs_print_condition(head, cond))  
                 goto out;  
1543          return true;          return true;
  out:  
         head->read_avail = pos;  
         return false;  
1544  }  }
1545    
1546  /**  /**
# Line 1129  static bool ccs_print_entry(struct ccs_i Line 1555  static bool ccs_print_entry(struct ccs_i
1555                              struct ccs_acl_info *ptr)                              struct ccs_acl_info *ptr)
1556  {  {
1557          const struct ccs_condition *cond = ptr->cond;          const struct ccs_condition *cond = ptr->cond;
1558          const u8 acl_type = ccs_acl_type2(ptr);          const u8 acl_type = ptr->type;
1559          if (acl_type & ACL_DELETED)          if (ptr->is_deleted)
1560                  return true;                  return true;
1561          if (acl_type == TYPE_SINGLE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH_ACL) {
1562                  struct ccs_single_path_acl_record *acl                  struct ccs_path_acl *acl
1563                          = container_of(ptr, struct ccs_single_path_acl_record,                          = container_of(ptr, struct ccs_path_acl, head);
1564                                         head);                  return ccs_print_path_acl(head, acl, cond);
                 return ccs_print_single_path_acl(head, acl, cond);  
1565          }          }
1566          if (acl_type == TYPE_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {
1567                  struct ccs_execute_handler_record *acl                  struct ccs_execute_handler_record *acl
1568                          = container_of(ptr, struct ccs_execute_handler_record,                          = container_of(ptr, struct ccs_execute_handler_record,
1569                                         head);                                         head);
1570                  const char *keyword = KEYWORD_EXECUTE_HANDLER;                  const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;
1571                  return ccs_print_execute_handler_record(head, keyword, acl);                  return ccs_print_execute_handler_record(head, keyword, acl);
1572          }          }
1573          if (acl_type == TYPE_DENIED_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1574                  struct ccs_execute_handler_record *acl                  struct ccs_execute_handler_record *acl
1575                          = container_of(ptr, struct ccs_execute_handler_record,                          = container_of(ptr, struct ccs_execute_handler_record,
1576                                         head);                                         head);
1577                  const char *keyword = KEYWORD_DENIED_EXECUTE_HANDLER;                  const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER;
1578                  return ccs_print_execute_handler_record(head, keyword, acl);                  return ccs_print_execute_handler_record(head, keyword, acl);
1579          }          }
1580          if (head->read_execute_only)          if (head->read_execute_only)
1581                  return true;                  return true;
1582          if (acl_type == TYPE_MKDEV_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER3_ACL) {
1583                  struct ccs_mkdev_acl_record *acl                  struct ccs_path_number3_acl *acl
1584                          = container_of(ptr, struct ccs_mkdev_acl_record, head);                          = container_of(ptr, struct ccs_path_number3_acl, head);
1585                  return ccs_print_mkdev_acl(head, acl, cond);                  return ccs_print_path_number3_acl(head, acl, cond);
1586          }          }
1587          if (acl_type == TYPE_DOUBLE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH2_ACL) {
1588                  struct ccs_double_path_acl_record *acl                  struct ccs_path2_acl *acl
1589                          = container_of(ptr, struct ccs_double_path_acl_record,                          = container_of(ptr, struct ccs_path2_acl, head);
1590                                         head);                  return ccs_print_path2_acl(head, acl, cond);
1591                  return ccs_print_double_path_acl(head, acl, cond);          }
1592          }          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1593          if (acl_type == TYPE_PATH_NUMBER_ACL) {                  struct ccs_path_number_acl *acl
1594                  struct ccs_path_number_acl_record *acl                          = container_of(ptr, struct ccs_path_number_acl, head);
                         = container_of(ptr, struct ccs_path_number_acl_record,  
                                        head);  
1595                  return ccs_print_path_number_acl(head, acl, cond);                  return ccs_print_path_number_acl(head, acl, cond);
1596          }          }
1597          if (acl_type == TYPE_ARGV0_ACL) {          if (acl_type == CCS_TYPE_ENV_ACL) {
1598                  struct ccs_argv0_acl_record *acl                  struct ccs_env_acl *acl
1599                          = 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);  
1600                  return ccs_print_env_acl(head, acl, cond);                  return ccs_print_env_acl(head, acl, cond);
1601          }          }
1602          if (acl_type == TYPE_CAPABILITY_ACL) {          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1603                  struct ccs_capability_acl_record *acl                  struct ccs_capability_acl *acl
1604                          = container_of(ptr, struct ccs_capability_acl_record,                          = container_of(ptr, struct ccs_capability_acl, head);
                                        head);  
1605                  return ccs_print_capability_acl(head, acl, cond);                  return ccs_print_capability_acl(head, acl, cond);
1606          }          }
1607          if (acl_type == TYPE_IP_NETWORK_ACL) {          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1608                  struct ccs_ip_network_acl_record *acl                  struct ccs_ip_network_acl *acl
1609                          = container_of(ptr, struct ccs_ip_network_acl_record,                          = container_of(ptr, struct ccs_ip_network_acl, head);
                                        head);  
1610                  return ccs_print_network_acl(head, acl, cond);                  return ccs_print_network_acl(head, acl, cond);
1611          }          }
1612          if (acl_type == TYPE_SIGNAL_ACL) {          if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1613                  struct ccs_signal_acl_record *acl                  struct ccs_signal_acl *acl
1614                          = container_of(ptr, struct ccs_signal_acl_record, head);                          = container_of(ptr, struct ccs_signal_acl, head);
1615                  return ccs_print_signal_acl(head, acl, cond);                  return ccs_print_signal_acl(head, acl, cond);
1616          }          }
1617          if (acl_type == TYPE_MOUNT_ACL) {          if (acl_type == CCS_TYPE_MOUNT_ACL) {
1618                  struct ccs_mount_acl_record *acl                  struct ccs_mount_acl *acl
1619                          = container_of(ptr, struct ccs_mount_acl_record, head);                          = container_of(ptr, struct ccs_mount_acl, head);
1620                  return ccs_print_mount_acl(head, acl, cond);                  return ccs_print_mount_acl(head, acl, cond);
1621          }          }
         if (acl_type == TYPE_UMOUNT_ACL) {  
                 struct ccs_umount_acl_record *acl  
                         = container_of(ptr, struct ccs_umount_acl_record, head);  
                 return ccs_print_umount_acl(head, acl, cond);  
         }  
         if (acl_type == TYPE_CHROOT_ACL) {  
                 struct ccs_chroot_acl_record *acl  
                         = container_of(ptr, struct ccs_chroot_acl_record, head);  
                 return ccs_print_chroot_acl(head, acl, cond);  
         }  
         if (acl_type == TYPE_PIVOT_ROOT_ACL) {  
                 struct ccs_pivot_root_acl_record *acl  
                         = container_of(ptr, struct ccs_pivot_root_acl_record,  
                                        head);  
                 return ccs_print_pivot_root_acl(head, acl, cond);  
         }  
         /* Workaround for gcc 3.2.2's inline bug. */  
         if (acl_type & ACL_DELETED)  
                 return true;  
1622          BUG(); /* This must not happen. */          BUG(); /* This must not happen. */
1623          return false;          return false;
1624  }  }
# Line 1231  static bool ccs_print_entry(struct ccs_i Line 1628  static bool ccs_print_entry(struct ccs_i
1628   *   *
1629   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1630   *   *
  * Returns 0.  
  *  
1631   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1632   */   */
1633  static int ccs_read_domain_policy(struct ccs_io_buffer *head)  static void ccs_read_domain_policy(struct ccs_io_buffer *head)
1634  {  {
1635          struct list_head *dpos;          struct list_head *dpos;
1636          struct list_head *apos;          struct list_head *apos;
         ccs_check_read_lock();  
1637          if (head->read_eof)          if (head->read_eof)
1638                  return 0;                  return;
1639          if (head->read_step == 0)          if (head->read_step == 0)
1640                  head->read_step = 1;                  head->read_step = 1;
1641          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 1656  static int ccs_read_domain_policy(struct
1656                          transition_failed = "transition_failed\n";                          transition_failed = "transition_failed\n";
1657                  if (domain->ignore_global_allow_read)                  if (domain->ignore_global_allow_read)
1658                          ignore_global_allow_read                          ignore_global_allow_read
1659                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1660                  if (domain->ignore_global_allow_env)                  if (domain->ignore_global_allow_env)
1661                          ignore_global_allow_env                          ignore_global_allow_env
1662                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
1663                  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"
1664                                     "%s%s%s%s\n", domain->domainname->name,                                     "%s%s%s%s\n", domain->domainname->name,
1665                                     domain->profile, quota_exceeded,                                     domain->profile, quota_exceeded,
1666                                     transition_failed,                                     transition_failed,
1667                                     ignore_global_allow_read,                                     ignore_global_allow_read,
1668                                     ignore_global_allow_env))                                     ignore_global_allow_env))
1669                          return 0;                          return;
1670                  head->read_step = 2;                  head->read_step = 2;
1671   acl_loop:   acl_loop:
1672                  if (head->read_step == 3)                  if (head->read_step == 3)
# Line 1283  static int ccs_read_domain_policy(struct Line 1677  static int ccs_read_domain_policy(struct
1677                          struct ccs_acl_info *ptr                          struct ccs_acl_info *ptr
1678                                  = list_entry(apos, struct ccs_acl_info, list);                                  = list_entry(apos, struct ccs_acl_info, list);
1679                          if (!ccs_print_entry(head, ptr))                          if (!ccs_print_entry(head, ptr))
1680                                  return 0;                                  return;
1681                  }                  }
1682                  head->read_step = 3;                  head->read_step = 3;
1683   tail_mark:   tail_mark:
1684                  if (!ccs_io_printf(head, "\n"))                  if (!ccs_io_printf(head, "\n"))
1685                          return 0;                          return;
1686                  head->read_step = 1;                  head->read_step = 1;
1687                  if (head->read_single_domain)                  if (head->read_single_domain)
1688                          break;                          break;
1689          }          }
1690          head->read_eof = true;          head->read_eof = true;
         return 0;  
1691  }  }
1692    
1693  /**  /**
# Line 1307  static int ccs_read_domain_policy(struct Line 1700  static int ccs_read_domain_policy(struct
1700   * This is equivalent to doing   * This is equivalent to doing
1701   *   *
1702   *     ( echo "select " $domainname; echo "use_profile " $profile ) |   *     ( echo "select " $domainname; echo "use_profile " $profile ) |
1703   *     /usr/lib/ccs/loadpolicy -d   *     /usr/sbin/ccs-loadpolicy -d
1704   *   *
1705   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1706   */   */
# Line 1317  static int ccs_write_domain_profile(stru Line 1710  static int ccs_write_domain_profile(stru
1710          char *cp = strchr(data, ' ');          char *cp = strchr(data, ' ');
1711          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
1712          unsigned int profile;          unsigned int profile;
         ccs_check_read_lock();  
1713          if (!cp)          if (!cp)
1714                  return -EINVAL;                  return -EINVAL;
1715          *cp = '\0';          *cp = '\0';
1716          profile = simple_strtoul(data, NULL, 10);          profile = simple_strtoul(data, NULL, 10);
1717          if (profile >= MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
1718                  return -EINVAL;                  return -EINVAL;
1719          domain = ccs_find_domain(cp + 1);          domain = ccs_find_domain(cp + 1);
1720          if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))          if (domain && (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile]))
1721                  domain->profile = (u8) profile;                  domain->profile = (u8) profile;
1722          return 0;          return 0;
1723  }  }
# Line 1335  static int ccs_write_domain_profile(stru Line 1727  static int ccs_write_domain_profile(stru
1727   *   *
1728   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1729   *   *
  * Returns list of profile number and domainname pairs.  
  *  
1730   * This is equivalent to doing   * This is equivalent to doing
1731   *   *
1732   *     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 1736  static int ccs_write_domain_profile(stru
1736   *   *
1737   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1738   */   */
1739  static int ccs_read_domain_profile(struct ccs_io_buffer *head)  static void ccs_read_domain_profile(struct ccs_io_buffer *head)
1740  {  {
1741          struct list_head *pos;          struct list_head *pos;
         ccs_check_read_lock();  
1742          if (head->read_eof)          if (head->read_eof)
1743                  return 0;                  return;
1744          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1745                  struct ccs_domain_info *domain;                  struct ccs_domain_info *domain;
1746                  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 1748  static int ccs_read_domain_profile(struc
1748                          continue;                          continue;
1749                  if (!ccs_io_printf(head, "%u %s\n", domain->profile,                  if (!ccs_io_printf(head, "%u %s\n", domain->profile,
1750                                     domain->domainname->name))                                     domain->domainname->name))
1751                          return 0;                          return;
1752          }          }
1753          head->read_eof = true;          head->read_eof = true;
         return 0;  
1754  }  }
1755    
1756  /**  /**
# Line 1389  static int ccs_write_pid(struct ccs_io_b Line 1777  static int ccs_write_pid(struct ccs_io_b
1777   *   *
1778   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1779   */   */
1780  static int ccs_read_pid(struct ccs_io_buffer *head)  static void ccs_read_pid(struct ccs_io_buffer *head)
1781  {  {
1782          char *buf = head->write_buf;          char *buf = head->write_buf;
1783          bool task_info = false;          bool task_info = false;
1784            bool global_pid = false;
1785          unsigned int pid;          unsigned int pid;
1786          struct task_struct *p;          struct task_struct *p;
1787          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1788          u32 ccs_flags = 0;          u32 ccs_flags = 0;
         ccs_check_read_lock();  
1789          /* Accessing write_buf is safe because head->io_sem is held. */          /* Accessing write_buf is safe because head->io_sem is held. */
1790          if (!buf)          if (!buf)
1791                  goto done; /* Do nothing if open(O_RDONLY). */                  return; /* Do nothing if open(O_RDONLY). */
1792          if (head->read_avail || head->read_eof)          if (head->read_avail || head->read_eof)
1793                  goto done;                  return;
1794          head->read_eof = true;          head->read_eof = true;
1795          if (ccs_str_starts(&buf, "info "))          if (ccs_str_starts(&buf, "info "))
1796                  task_info = true;                  task_info = true;
1797            if (ccs_str_starts(&buf, "global-pid "))
1798                    global_pid = true;
1799          pid = (unsigned int) simple_strtoul(buf, NULL, 10);          pid = (unsigned int) simple_strtoul(buf, NULL, 10);
         /***** CRITICAL SECTION START *****/  
1800          read_lock(&tasklist_lock);          read_lock(&tasklist_lock);
1801    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1802            if (global_pid)
1803                    p = find_task_by_pid_ns(pid, &init_pid_ns);
1804            else
1805                    p = find_task_by_vpid(pid);
1806    #else
1807          p = find_task_by_pid(pid);          p = find_task_by_pid(pid);
1808    #endif
1809          if (p) {          if (p) {
1810                  domain = ccs_task_domain(p);                  domain = ccs_task_domain(p);
1811                  ccs_flags = p->ccs_flags;                  ccs_flags = p->ccs_flags;
1812          }          }
1813          read_unlock(&tasklist_lock);          read_unlock(&tasklist_lock);
         /***** CRITICAL SECTION END *****/  
1814          if (!domain)          if (!domain)
1815                  goto done;                  return;
1816          if (!task_info)          if (!task_info)
1817                  ccs_io_printf(head, "%u %u %s", pid, domain->profile,                  ccs_io_printf(head, "%u %u %s", pid, domain->profile,
1818                                domain->domainname->name);                                domain->domainname->name);
1819          else          else
1820                  ccs_io_printf(head, "%u manager=%s execute_handler=%s "                  ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1821                                "state[0]=%u state[1]=%u state[2]=%u", pid,                                "state[0]=%u state[1]=%u state[2]=%u", pid,
1822                                ccs_flags & CCS_TASK_IS_POLICY_MANAGER ?                                ccs_yesno(ccs_flags &
1823                                "yes" : "no",                                          CCS_TASK_IS_POLICY_MANAGER),
1824                                ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER ?                                ccs_yesno(ccs_flags &
1825                                "yes" : "no",                                          CCS_TASK_IS_EXECUTE_HANDLER),
1826                                (u8) (ccs_flags >> 24),                                (u8) (ccs_flags >> 24),
1827                                (u8) (ccs_flags >> 16),                                (u8) (ccs_flags >> 16),
1828                                (u8) (ccs_flags >> 8));                                (u8) (ccs_flags >> 8));
  done:  
         return 0;  
1829  }  }
1830    
1831  /**  /**
# Line 1445  static int ccs_read_pid(struct ccs_io_bu Line 1838  static int ccs_read_pid(struct ccs_io_bu
1838  static int ccs_write_exception_policy(struct ccs_io_buffer *head)  static int ccs_write_exception_policy(struct ccs_io_buffer *head)
1839  {  {
1840          char *data = head->write_buf;          char *data = head->write_buf;
1841          bool is_delete = ccs_str_starts(&data, KEYWORD_DELETE);          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1842          if (ccs_str_starts(&data, KEYWORD_KEEP_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN))
1843                  return ccs_write_domain_keeper_policy(data, false, is_delete);                  return ccs_write_domain_keeper_policy(data, false, is_delete);
1844          if (ccs_str_starts(&data, KEYWORD_NO_KEEP_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN))
1845                  return ccs_write_domain_keeper_policy(data, true, is_delete);                  return ccs_write_domain_keeper_policy(data, true, is_delete);
1846          if (ccs_str_starts(&data, KEYWORD_INITIALIZE_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN))
1847                  return ccs_write_domain_initializer_policy(data, false,                  return ccs_write_domain_initializer_policy(data, false,
1848                                                             is_delete);                                                             is_delete);
1849          if (ccs_str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN))          if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN))
1850                  return ccs_write_domain_initializer_policy(data, true,                  return ccs_write_domain_initializer_policy(data, true,
1851                                                             is_delete);                                                             is_delete);
1852          if (ccs_str_starts(&data, KEYWORD_AGGREGATOR))          if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR))
1853                  return ccs_write_aggregator_policy(data, is_delete);                  return ccs_write_aggregator_policy(data, is_delete);
1854          if (ccs_str_starts(&data, KEYWORD_ALLOW_READ))          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ))
1855                  return ccs_write_globally_readable_policy(data, is_delete);                  return ccs_write_globally_readable_policy(data, is_delete);
1856          if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))
1857                  return ccs_write_globally_usable_env_policy(data, is_delete);                  return ccs_write_globally_usable_env_policy(data, is_delete);
1858          if (ccs_str_starts(&data, KEYWORD_FILE_PATTERN))          if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN))
1859                  return ccs_write_pattern_policy(data, is_delete);                  return ccs_write_pattern_policy(data, is_delete);
1860          if (ccs_str_starts(&data, KEYWORD_PATH_GROUP))          if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP))
1861                  return ccs_write_path_group_policy(data, is_delete);                  return ccs_write_path_group_policy(data, is_delete);
1862          if (ccs_str_starts(&data, KEYWORD_NUMBER_GROUP))          if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP))
1863                  return ccs_write_number_group_policy(data, is_delete);                  return ccs_write_number_group_policy(data, is_delete);
1864          if (ccs_str_starts(&data, KEYWORD_DENY_REWRITE))          if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE))
1865                  return ccs_write_no_rewrite_policy(data, is_delete);                  return ccs_write_no_rewrite_policy(data, is_delete);
1866          if (ccs_str_starts(&data, KEYWORD_ADDRESS_GROUP))          if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP))
1867                  return ccs_write_address_group_policy(data, is_delete);                  return ccs_write_address_group_policy(data, is_delete);
1868          if (ccs_str_starts(&data, KEYWORD_DENY_AUTOBIND))          if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND))
1869                  return ccs_write_reserved_port_policy(data, is_delete);                  return ccs_write_reserved_port_policy(data, is_delete);
1870          return -EINVAL;          return -EINVAL;
1871  }  }
# Line 1482  static int ccs_write_exception_policy(st Line 1875  static int ccs_write_exception_policy(st
1875   *   *
1876   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1877   *   *
  * Returns 0 on success, -EINVAL otherwise.  
  *  
1878   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1879   */   */
1880  static int ccs_read_exception_policy(struct ccs_io_buffer *head)  static void ccs_read_exception_policy(struct ccs_io_buffer *head)
1881  {  {
1882          ccs_check_read_lock();          if (head->read_eof)
1883          if (!head->read_eof) {                  return;
1884                  switch (head->read_step) {          switch (head->read_step) {
1885                  case 0:          case 0:
1886                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1887                          head->read_step = 1;                  head->read_step = 1;
1888                  case 1:          case 1:
1889                          if (!ccs_read_domain_keeper_policy(head))                  if (!ccs_read_domain_keeper_policy(head))
1890                                  break;                          break;
1891                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1892                          head->read_step = 2;                  head->read_step = 2;
1893                  case 2:          case 2:
1894                          if (!ccs_read_globally_readable_policy(head))                  if (!ccs_read_globally_readable_policy(head))
1895                                  break;                          break;
1896                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1897                          head->read_step = 3;                  head->read_step = 3;
1898                  case 3:          case 3:
1899                          if (!ccs_read_globally_usable_env_policy(head))                  if (!ccs_read_globally_usable_env_policy(head))
1900                                  break;                          break;
1901                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1902                          head->read_step = 4;                  head->read_step = 4;
1903                  case 4:          case 4:
1904                          if (!ccs_read_domain_initializer_policy(head))                  if (!ccs_read_domain_initializer_policy(head))
1905                                  break;                          break;
1906                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1907                          head->read_step = 6;                  head->read_step = 6;
1908                  case 6:          case 6:
1909                          if (!ccs_read_aggregator_policy(head))                  if (!ccs_read_aggregator_policy(head))
1910                                  break;                          break;
1911                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1912                          head->read_step = 7;                  head->read_step = 7;
1913                  case 7:          case 7:
1914                          if (!ccs_read_file_pattern(head))                  if (!ccs_read_file_pattern(head))
1915                                  break;                          break;
1916                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1917                          head->read_step = 8;                  head->read_step = 8;
1918                  case 8:          case 8:
1919                          if (!ccs_read_no_rewrite_policy(head))                  if (!ccs_read_no_rewrite_policy(head))
1920                                  break;                          break;
1921                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1922                          head->read_step = 9;                  head->read_step = 9;
1923                  case 9:          case 9:
1924                          if (!ccs_read_path_group_policy(head))                  if (!ccs_read_path_group_policy(head))
1925                                  break;                          break;
1926                          head->read_var1 = NULL;                  head->read_var1 = NULL;
1927                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1928                          head->read_step = 10;                  head->read_step = 10;
1929                  case 10:          case 10:
1930                          if (!ccs_read_number_group_policy(head))                  if (!ccs_read_number_group_policy(head))
1931                                  break;                          break;
1932                          head->read_var1 = NULL;                  head->read_var1 = NULL;
1933                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1934                          head->read_step = 11;                  head->read_step = 11;
1935                  case 11:          case 11:
1936                          if (!ccs_read_address_group_policy(head))                  if (!ccs_read_address_group_policy(head))
1937                                  break;                          break;
1938                          head->read_var2 = NULL;                  head->read_var2 = NULL;
1939                          head->read_step = 12;                  head->read_step = 12;
1940                  case 12:          case 12:
1941                          if (!ccs_read_reserved_port_policy(head))                  if (!ccs_read_reserved_port_policy(head))
1942                            break;
1943                    head->read_eof = true;
1944            }
1945    }
1946    
1947    /**
1948     * ccs_get_argv0 - Get argv[0].
1949     *
1950     * @ee: Pointer to "struct ccs_execve_entry".
1951     *
1952     * Returns true on success, false otherwise.
1953     */
1954    static bool ccs_get_argv0(struct ccs_execve_entry *ee)
1955    {
1956            struct linux_binprm *bprm = ee->bprm;
1957            char *arg_ptr = ee->tmp;
1958            int arg_len = 0;
1959            unsigned long pos = bprm->p;
1960            int offset = pos % PAGE_SIZE;
1961            bool done = false;
1962            if (!bprm->argc)
1963                    goto out;
1964            while (1) {
1965                    if (!ccs_dump_page(bprm, pos, &ee->dump))
1966                            goto out;
1967                    pos += PAGE_SIZE - offset;
1968                    /* Read. */
1969                    while (offset < PAGE_SIZE) {
1970                            const char *kaddr = ee->dump.data;
1971                            const unsigned char c = kaddr[offset++];
1972                            if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
1973                                    if (c == '\\') {
1974                                            arg_ptr[arg_len++] = '\\';
1975                                            arg_ptr[arg_len++] = '\\';
1976                                    } else if (c > ' ' && c < 127) {
1977                                            arg_ptr[arg_len++] = c;
1978                                    } else {
1979                                            arg_ptr[arg_len++] = '\\';
1980                                            arg_ptr[arg_len++] = (c >> 6) + '0';
1981                                            arg_ptr[arg_len++]
1982                                                    = ((c >> 3) & 7) + '0';
1983                                            arg_ptr[arg_len++] = (c & 7) + '0';
1984                                    }
1985                            } else {
1986                                    arg_ptr[arg_len] = '\0';
1987                                    done = true;
1988                                  break;                                  break;
1989                          head->read_eof = true;                          }
1990                    }
1991                    offset = 0;
1992                    if (done)
1993                          break;                          break;
1994                  default:          }
1995                          return -EINVAL;          return true;
1996     out:
1997            return false;
1998    }
1999    
2000    /**
2001     * ccs_get_execute_condition - Get condition part for execute requests.
2002     *
2003     * @ee: Pointer to "struct ccs_execve_entry".
2004     *
2005     * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
2006     */
2007    static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry
2008                                                           *ee)
2009    {
2010            struct ccs_condition *cond;
2011            char *buf;
2012            int len = 256;
2013            char *realpath = NULL;
2014            char *argv0 = NULL;
2015            const struct ccs_profile *profile = ccs_profile(ee->r.domain->profile);
2016            if (profile->learning->learning_exec_realpath) {
2017                    struct file *file = ee->bprm->file;
2018    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2019                    struct path path = { file->f_vfsmnt, file->f_dentry };
2020                    realpath = ccs_realpath_from_path(&path);
2021    #else
2022                    realpath = ccs_realpath_from_path(&file->f_path);
2023    #endif
2024                    if (realpath)
2025                            len += strlen(realpath) + 17;
2026            }
2027            if (profile->learning->learning_exec_argv0) {
2028                    if (ccs_get_argv0(ee)) {
2029                            argv0 = ee->tmp;
2030                            len += strlen(argv0) + 16;
2031                  }                  }
2032          }          }
2033          return 0;          buf = kmalloc(len, GFP_KERNEL);
2034            if (!buf) {
2035                    kfree(realpath);
2036                    return NULL;
2037            }
2038            snprintf(buf, len - 1, "if");
2039            if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
2040                    const int pos = strlen(buf);
2041                    snprintf(buf + pos, len - pos - 1,
2042                             " task.type=execute_handler");
2043            }
2044            if (realpath) {
2045                    const int pos = strlen(buf);
2046                    snprintf(buf + pos, len - pos - 1, " exec.realpath=\"%s\"",
2047                             realpath);
2048                    kfree(realpath);
2049            }
2050            if (argv0) {
2051                    const int pos = strlen(buf);
2052                    snprintf(buf + pos, len - pos - 1, " exec.argv[0]=\"%s\"",
2053                             argv0);
2054            }
2055            cond = ccs_get_condition(buf);
2056            kfree(buf);
2057            return cond;
2058    }
2059    
2060    /**
2061     * ccs_get_symlink_condition - Get condition part for symlink requests.
2062     *
2063     * @r: Pointer to "struct ccs_request_info".
2064     *
2065     * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
2066     */
2067    static struct ccs_condition *ccs_get_symlink_condition(struct ccs_request_info
2068                                                           *r)
2069    {
2070            struct ccs_condition *cond;
2071            char *buf;
2072            int len = 256;
2073            const char *symlink = NULL;
2074            const struct ccs_profile *profile = ccs_profile(r->profile);
2075            if (profile->learning->learning_symlink_target) {
2076                    symlink = r->obj->symlink_target->name;
2077                    len += strlen(symlink) + 18;
2078            }
2079            buf = kmalloc(len, GFP_KERNEL);
2080            if (!buf)
2081                    return NULL;
2082            snprintf(buf, len - 1, "if");
2083            if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {
2084                    const int pos = strlen(buf);
2085                    snprintf(buf + pos, len - pos - 1,
2086                             " task.type=execute_handler");
2087            }
2088            if (symlink) {
2089                    const int pos = strlen(buf);
2090                    snprintf(buf + pos, len - pos - 1, " symlink.target=\"%s\"",
2091                             symlink);
2092            }
2093            cond = ccs_get_condition(buf);
2094            kfree(buf);
2095            return cond;
2096  }  }
2097    
2098  /* Wait queue for ccs_query_list. */  /* Wait queue for ccs_query_list. */
# Line 1581  static LIST_HEAD(ccs_query_list); Line 2118  static LIST_HEAD(ccs_query_list);
2118  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
2119    
2120  /**  /**
2121   * ccs_check_supervisor - Ask for the supervisor's decision.   * ccs_supervisor - Ask for the supervisor's decision.
2122   *   *
2123   * @r:       Pointer to "struct ccs_request_info".   * @r:       Pointer to "struct ccs_request_info".
2124   * @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 2126  static atomic_t ccs_query_observers = AT
2126   * Returns 0 if the supervisor decided to permit the access request which   * Returns 0 if the supervisor decided to permit the access request which
2127   * violated the policy in enforcing mode, 1 if the supervisor decided to   * violated the policy in enforcing mode, 1 if the supervisor decided to
2128   * retry the access request which violated the policy in enforcing mode,   * retry the access request which violated the policy in enforcing mode,
2129   * -EPERM otherwise.   * 0 if it is not in enforcing mode, -EPERM otherwise.
2130   */   */
2131  int ccs_check_supervisor(struct ccs_request_info *r, const char *fmt, ...)  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
2132  {  {
2133          va_list args;          va_list args;
2134          int error = -EPERM;          int error = -EPERM;
# Line 1603  int ccs_check_supervisor(struct ccs_requ Line 2140  int ccs_check_supervisor(struct ccs_requ
2140          char *header;          char *header;
2141          if (!r->domain)          if (!r->domain)
2142                  r->domain = ccs_current_domain();                  r->domain = ccs_current_domain();
2143            switch (r->mode) {
2144                    char *buffer;
2145                    struct ccs_condition *cond;
2146            case CCS_CONFIG_LEARNING:
2147                    if (!ccs_domain_quota_ok(r))
2148                            return 0;
2149                    va_start(args, fmt);
2150                    len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
2151                    va_end(args);
2152                    buffer = kmalloc(len, GFP_KERNEL);
2153                    if (!buffer)
2154                            return 0;
2155                    va_start(args, fmt);
2156                    vsnprintf(buffer, len - 1, fmt, args);
2157                    va_end(args);
2158                    ccs_normalize_line(buffer);
2159                    if (r->ee && !strncmp(buffer, "allow_execute ", 14))
2160                            cond = ccs_get_execute_condition(r->ee);
2161                    else if (r->obj && r->obj->symlink_target)
2162                            cond = ccs_get_symlink_condition(r);
2163                    else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
2164                            char str[] = "if task.type=execute_handler";
2165                            cond = ccs_get_condition(str);
2166                    } else
2167                            cond = NULL;
2168                    ccs_write_domain_policy2(buffer, r->domain, cond, false);
2169                    ccs_put_condition(cond);
2170                    kfree(buffer);
2171                    /* fall through */
2172            case CCS_CONFIG_PERMISSIVE:
2173                    return 0;
2174            }
2175          if (!atomic_read(&ccs_query_observers)) {          if (!atomic_read(&ccs_query_observers)) {
2176                  int i;                  int i;
2177                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
2178                          return -EPERM;                          return -EPERM;
2179                  for (i = 0; i < ccs_check_flags(r->domain, CCS_SLEEP_PERIOD);                  for (i = 0; i < ccs_profile(r->domain->profile)->enforcing->
2180                       i++) {                               enforcing_penalty; i++) {
2181                          set_current_state(TASK_INTERRUPTIBLE);                          set_current_state(TASK_INTERRUPTIBLE);
2182                          schedule_timeout(HZ / 10);                          schedule_timeout(HZ / 10);
2183                  }                  }
# Line 1623  int ccs_check_supervisor(struct ccs_requ Line 2192  int ccs_check_supervisor(struct ccs_requ
2192          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
2193          if (!ccs_query_entry)          if (!ccs_query_entry)
2194                  goto out;                  goto out;
2195            len = ccs_round2(len);
2196          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
2197          if (!ccs_query_entry->query)          if (!ccs_query_entry->query)
2198                  goto out;                  goto out;
2199          INIT_LIST_HEAD(&ccs_query_entry->list);          INIT_LIST_HEAD(&ccs_query_entry->list);
         /***** CRITICAL SECTION START *****/  
2200          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2201          if (ccs_quota_for_query && ccs_query_memory_size + len +          if (ccs_quota_for_query && ccs_query_memory_size + len +
2202              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 2206  int ccs_check_supervisor(struct ccs_requ
2206                  ccs_query_entry->serial = ccs_serial++;                  ccs_query_entry->serial = ccs_serial++;
2207          }          }
2208          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2209          if (quota_exceeded)          if (quota_exceeded)
2210                  goto out;                  goto out;
2211          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 2216  int ccs_check_supervisor(struct ccs_requ
2216          vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);          vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
2217          ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;          ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
2218          va_end(args);          va_end(args);
         /***** CRITICAL SECTION START *****/  
2219          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2220          list_add_tail(&ccs_query_entry->list, &ccs_query_list);          list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2221          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2222          /* Give 10 seconds for supervisor's opinion. */          /* Give 10 seconds for supervisor's opinion. */
2223          for (ccs_query_entry->timer = 0;          for (ccs_query_entry->timer = 0;
2224               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 2229  int ccs_check_supervisor(struct ccs_requ
2229                  if (ccs_query_entry->answer)                  if (ccs_query_entry->answer)
2230                          break;                          break;
2231          }          }
         /***** CRITICAL SECTION START *****/  
2232          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2233          list_del(&ccs_query_entry->list);          list_del(&ccs_query_entry->list);
2234          ccs_query_memory_size -= len + sizeof(*ccs_query_entry);          ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
2235          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2236          switch (ccs_query_entry->answer) {          switch (ccs_query_entry->answer) {
2237          case 3: /* Asked to retry by administrator. */          case 3: /* Asked to retry by administrator. */
2238                  error = 1;                  error = 1;
# Line 1709  static int ccs_poll_query(struct file *f Line 2273  static int ccs_poll_query(struct file *f
2273          bool found = false;          bool found = false;
2274          u8 i;          u8 i;
2275          for (i = 0; i < 2; i++) {          for (i = 0; i < 2; i++) {
                 /***** CRITICAL SECTION START *****/  
2276                  spin_lock(&ccs_query_list_lock);                  spin_lock(&ccs_query_list_lock);
2277                  list_for_each(tmp, &ccs_query_list) {                  list_for_each(tmp, &ccs_query_list) {
2278                          struct ccs_query_entry *ptr                          struct ccs_query_entry *ptr
# Line 1720  static int ccs_poll_query(struct file *f Line 2283  static int ccs_poll_query(struct file *f
2283                          break;                          break;
2284                  }                  }
2285                  spin_unlock(&ccs_query_list_lock);                  spin_unlock(&ccs_query_list_lock);
                 /***** CRITICAL SECTION END *****/  
2286                  if (found)                  if (found)
2287                          return POLLIN | POLLRDNORM;                          return POLLIN | POLLRDNORM;
2288                  if (i)                  if (i)
# Line 1734  static int ccs_poll_query(struct file *f Line 2296  static int ccs_poll_query(struct file *f
2296   * ccs_read_query - Read access requests which violated policy in enforcing mode.   * ccs_read_query - Read access requests which violated policy in enforcing mode.
2297   *   *
2298   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns 0.  
2299   */   */
2300  static int ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2301  {  {
2302          struct list_head *tmp;          struct list_head *tmp;
2303          int pos = 0;          int pos = 0;
2304          int len = 0;          int len = 0;
2305          char *buf;          char *buf;
2306          if (head->read_avail)          if (head->read_avail)
2307                  return 0;                  return;
2308          if (head->read_buf) {          if (head->read_buf) {
2309                  kfree(head->read_buf);                  kfree(head->read_buf);
2310                  head->read_buf = NULL;                  head->read_buf = NULL;
2311                  head->readbuf_size = 0;                  head->readbuf_size = 0;
2312          }          }
         /***** CRITICAL SECTION START *****/  
2313          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2314          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2315                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 1763  static int ccs_read_query(struct ccs_io_ Line 2322  static int ccs_read_query(struct ccs_io_
2322                  break;                  break;
2323          }          }
2324          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2325          if (!len) {          if (!len) {
2326                  head->read_step = 0;                  head->read_step = 0;
2327                  return 0;                  return;
2328          }          }
2329          buf = kzalloc(len, GFP_KERNEL);          buf = kzalloc(len, GFP_KERNEL);
2330          if (!buf)          if (!buf)
2331                  return 0;                  return;
2332          pos = 0;          pos = 0;
         /***** CRITICAL SECTION START *****/  
2333          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2334          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2335                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 1790  static int ccs_read_query(struct ccs_io_ Line 2347  static int ccs_read_query(struct ccs_io_
2347                  break;                  break;
2348          }          }
2349          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2350          if (buf[0]) {          if (buf[0]) {
2351                  head->read_avail = len;                  head->read_avail = len;
2352                  head->readbuf_size = head->read_avail;                  head->readbuf_size = head->read_avail;
# Line 1799  static int ccs_read_query(struct ccs_io_ Line 2355  static int ccs_read_query(struct ccs_io_
2355          } else {          } else {
2356                  kfree(buf);                  kfree(buf);
2357          }          }
         return 0;  
2358  }  }
2359    
2360  /**  /**
# Line 1815  static int ccs_write_answer(struct ccs_i Line 2370  static int ccs_write_answer(struct ccs_i
2370          struct list_head *tmp;          struct list_head *tmp;
2371          unsigned int serial;          unsigned int serial;
2372          unsigned int answer;          unsigned int answer;
         /***** CRITICAL SECTION START *****/  
2373          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2374          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2375                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 1823  static int ccs_write_answer(struct ccs_i Line 2377  static int ccs_write_answer(struct ccs_i
2377                  ptr->timer = 0;                  ptr->timer = 0;
2378          }          }
2379          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2380          if (sscanf(data, "A%u=%u", &serial, &answer) != 2)          if (sscanf(data, "A%u=%u", &serial, &answer) != 2)
2381                  return -EINVAL;                  return -EINVAL;
         /***** CRITICAL SECTION START *****/  
2382          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2383          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2384                  struct ccs_query_entry *ptr                  struct ccs_query_entry *ptr
# Line 1838  static int ccs_write_answer(struct ccs_i Line 2390  static int ccs_write_answer(struct ccs_i
2390                  break;                  break;
2391          }          }
2392          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
         /***** CRITICAL SECTION END *****/  
2393          return 0;          return 0;
2394  }  }
2395    
# Line 1846  static int ccs_write_answer(struct ccs_i Line 2397  static int ccs_write_answer(struct ccs_i
2397   * ccs_read_version: Get version.   * ccs_read_version: Get version.
2398   *   *
2399   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns version information.  
2400   */   */
2401  static int ccs_read_version(struct ccs_io_buffer *head)  static void ccs_read_version(struct ccs_io_buffer *head)
2402  {  {
2403          if (!head->read_eof) {          if (head->read_eof)
2404                  ccs_io_printf(head, "1.7.0-pre");                  return;
2405                  head->read_eof = true;          ccs_io_printf(head, "1.7.1-pre");
2406          }          head->read_eof = true;
         return 0;  
2407  }  }
2408    
2409  /**  /**
2410   * ccs_read_self_domain - Get the current process's domainname.   * ccs_read_self_domain - Get the current process's domainname.
2411   *   *
2412   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
  *  
  * Returns the current process's domainname.  
2413   */   */
2414  static int ccs_read_self_domain(struct ccs_io_buffer *head)  static void ccs_read_self_domain(struct ccs_io_buffer *head)
2415  {  {
2416          if (!head->read_eof) {          if (head->read_eof)
2417                  /*                  return;
2418                   * ccs_current_domain()->domainname != NULL          /*
2419                   * because every process belongs to a domain and           * ccs_current_domain()->domainname != NULL because every process
2420                   * the domain's name cannot be NULL.           * belongs to a domain and the domain's name cannot be NULL.
2421                   */           */
2422                  ccs_io_printf(head, "%s",          ccs_io_printf(head, "%s", ccs_current_domain()->domainname->name);
2423                                ccs_current_domain()->domainname->name);          head->read_eof = true;
                 head->read_eof = true;  
         }  
         return 0;  
2424  }  }
2425    
2426  /**  /**
# Line 1962  int ccs_open_control(const u8 type, stru Line 2505  int ccs_open_control(const u8 type, stru
2505                   */                   */
2506                  head->read = NULL;                  head->read = NULL;
2507                  head->poll = NULL;                  head->poll = NULL;
2508          } else if (type != CCS_QUERY &&          } else if (!head->poll) {
2509                     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.  
                  */  
2510                  if (!head->readbuf_size)                  if (!head->readbuf_size)
2511                          head->readbuf_size = 4096 * 2;                          head->readbuf_size = 4096;
2512                  head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);                  head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
2513                  if (!head->read_buf) {                  if (!head->read_buf) {
2514                          kfree(head);                          kfree(head);
# Line 1983  int ccs_open_control(const u8 type, stru Line 2522  int ccs_open_control(const u8 type, stru
2522                   */                   */
2523                  head->write = NULL;                  head->write = NULL;
2524          } else if (head->write) {          } else if (head->write) {
2525                  head->writebuf_size = 4096 * 2;                  head->writebuf_size = 4096;
2526                  head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);                  head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
2527                  if (!head->write_buf) {                  if (!head->write_buf) {
2528                          kfree(head->read_buf);                          kfree(head->read_buf);
# Line 2004  int ccs_open_control(const u8 type, stru Line 2543  int ccs_open_control(const u8 type, stru
2543                  ccs_read_control(file, NULL, 0);                  ccs_read_control(file, NULL, 0);
2544          /*          /*
2545           * If the file is /proc/ccs/query , increment the observer counter.           * If the file is /proc/ccs/query , increment the observer counter.
2546           * The obserber counter is used by ccs_check_supervisor() to see if           * The obserber counter is used by ccs_supervisor() to see if
2547           * there is some process monitoring /proc/ccs/query.           * there is some process monitoring /proc/ccs/query.
2548           */           */
2549          else if (type == CCS_QUERY)          else if (type == CCS_QUERY)
# Line 2019  int ccs_open_control(const u8 type, stru Line 2558  int ccs_open_control(const u8 type, stru
2558   * @wait: Pointer to "poll_table".   * @wait: Pointer to "poll_table".
2559   *   *
2560   * Waits for read readiness.   * Waits for read readiness.
2561   * /proc/ccs/query is handled by /usr/lib/ccs/ccs-queryd and   * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and
2562   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
2563   * /usr/lib/ccs/ccs-auditd.   * /usr/sbin/ccs-auditd .
2564   */   */
2565  int ccs_poll_control(struct file *file, poll_table *wait)  int ccs_poll_control(struct file *file, poll_table *wait)
2566  {  {
# Line 2052  int ccs_read_control(struct file *file, Line 2591  int ccs_read_control(struct file *file,
2591                  return -EFAULT;                  return -EFAULT;
2592          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2593                  return -EINTR;                  return -EINTR;
2594          /* Call the policy handler. */          while (1) {
2595          len = head->read(head);                  /* Call the policy handler. */
2596          if (len < 0)                  head->read(head);
2597                  goto out;                  /* Write to buffer. */
2598          /* Write to buffer. */                  len = head->read_avail;
2599          len = head->read_avail;                  if (len || head->poll || head->read_eof)
2600                            break;
2601                    len = head->readbuf_size * 2;
2602                    cp = kzalloc(len, GFP_KERNEL);
2603                    if (!cp) {
2604                            len = -ENOMEM;
2605                            goto out;
2606                    }
2607                    kfree(head->read_buf);
2608                    head->read_buf = cp;
2609                    head->readbuf_size = len;
2610            }
2611          if (len > buffer_len)          if (len > buffer_len)
2612                  len = buffer_len;                  len = buffer_len;
2613          if (!len)          if (!len)
# Line 2106  int ccs_write_control(struct file *file, Line 2656  int ccs_write_control(struct file *file,
2656          while (avail_len > 0) {          while (avail_len > 0) {
2657                  char c;                  char c;
2658                  if (head->write_avail >= head->writebuf_size - 1) {                  if (head->write_avail >= head->writebuf_size - 1) {
2659                          error = -ENOMEM;                          const int len = head->writebuf_size * 2;
2660                          break;                          char *cp = kzalloc(len, GFP_KERNEL);
2661                  } else if (get_user(c, buffer)) {                          if (!cp) {
2662                                    error = -ENOMEM;
2663                                    break;
2664                            }
2665                            memmove(cp, cp0, head->write_avail);
2666                            kfree(cp0);
2667                            head->write_buf = cp;
2668                            cp0 = cp;
2669                            head->writebuf_size = len;
2670                    }
2671                    if (get_user(c, buffer)) {
2672                          error = -EFAULT;                          error = -EFAULT;
2673                          break;                          break;
2674                  }                  }

Legend:
Removed from v.2888  
changed lines
  Added in v.3131

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