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

Subversion リポジトリの参照

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

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

revision 4056 by kumaneko, Sat Oct 9 23:48:20 2010 UTC revision 5526 by kumaneko, Mon Oct 3 07:12:14 2011 UTC
# Line 1  Line 1 
1  /*  /*
2   * security/ccsecurity/policy_io.c   * security/ccsecurity/policy_io.c
3   *   *
4   * Copyright (C) 2005-2010  NTT DATA CORPORATION   * Copyright (C) 2005-2011  NTT DATA CORPORATION
  *  
  * Version: 1.8.0-pre   2010/10/10  
  *  
  * This file is applicable to both 2.4.30 and 2.6.11 and later.  
  * See README.ccs for ChangeLog.  
5   *   *
6     * Version: 1.8.3   2011/09/29
7   */   */
8    
9  #include "internal.h"  #include "internal.h"
10    
11  /* Profile version. Currently only 20100903 is defined. */  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
12  static unsigned int ccs_profile_version;  
13    /**
14     * __wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
15     *
16     * @wq:        The waitqueue to wait on.
17     * @condition: A C expression for the event to wait for.
18     * @ret:       Timeout, in jiffies.
19     *
20     * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
21     * signal, and the remaining jiffies otherwise if the condition evaluated to
22     * true before the timeout elapsed.
23     *
24     * This is for compatibility with older kernels.
25     */
26    #define __wait_event_interruptible_timeout(wq, condition, ret)          \
27    do {                                                                    \
28            wait_queue_t __wait;                                            \
29            init_waitqueue_entry(&__wait, current);                         \
30                                                                            \
31            add_wait_queue(&wq, &__wait);                                   \
32            for (;;) {                                                      \
33                    set_current_state(TASK_INTERRUPTIBLE);                  \
34                    if (condition)                                          \
35                            break;                                          \
36                    if (!signal_pending(current)) {                         \
37                            ret = schedule_timeout(ret);                    \
38                            if (!ret)                                       \
39                                    break;                                  \
40                            continue;                                       \
41                    }                                                       \
42                    ret = -ERESTARTSYS;                                     \
43                    break;                                                  \
44            }                                                               \
45            current->state = TASK_RUNNING;                                  \
46            remove_wait_queue(&wq, &__wait);                                \
47    } while (0)
48    
49    /**
50     * wait_event_interruptible_timeout - Sleep until a condition gets true or a timeout elapses.
51     *
52     * @wq:        The waitqueue to wait on.
53     * @condition: A C expression for the event to wait for.
54     * @timeout:   Timeout, in jiffies.
55     *
56     * Returns 0 if the @timeout elapsed, -ERESTARTSYS if it was interrupted by a
57     * signal, and the remaining jiffies otherwise if the condition evaluated to
58     * true before the timeout elapsed.
59     *
60     * This is for compatibility with older kernels.
61     */
62    #define wait_event_interruptible_timeout(wq, condition, timeout)        \
63    ({                                                                      \
64            long __ret = timeout;                                           \
65            if (!(condition))                                               \
66                    __wait_event_interruptible_timeout(wq, condition, __ret); \
67            __ret;                                                          \
68    })
69    
70  /* Profile table. Memory is allocated as needed. */  #endif
 static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];  
71    
72  /* String table for functionality that takes 4 modes. */  /**
73     * list_for_each_cookie - iterate over a list with cookie.
74     *
75     * @pos:  Pointer to "struct list_head".
76     * @head: Pointer to "struct list_head".
77     */
78    #define list_for_each_cookie(pos, head)                                 \
79            for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
80                 pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
81    
82    /* String table for operation mode. */
83  const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {  const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
84          [CCS_CONFIG_DISABLED]   = "disabled",          [CCS_CONFIG_DISABLED]   = "disabled",
85          [CCS_CONFIG_LEARNING]   = "learning",          [CCS_CONFIG_LEARNING]   = "learning",
# Line 26  const char * const ccs_mode[CCS_CONFIG_M Line 87  const char * const ccs_mode[CCS_CONFIG_M
87          [CCS_CONFIG_ENFORCING]  = "enforcing"          [CCS_CONFIG_ENFORCING]  = "enforcing"
88  };  };
89    
90  /* String table for /proc/ccs/profile */  /* String table for /proc/ccs/profile interface. */
91  const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX  const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
92                                      + CCS_MAX_MAC_CATEGORY_INDEX] = {                                      + CCS_MAX_MAC_CATEGORY_INDEX] = {
93            /* CONFIG::file group */
94          [CCS_MAC_FILE_EXECUTE]    = "execute",          [CCS_MAC_FILE_EXECUTE]    = "execute",
95          [CCS_MAC_FILE_OPEN]       = "open",          [CCS_MAC_FILE_OPEN]       = "open",
96          [CCS_MAC_FILE_CREATE]     = "create",          [CCS_MAC_FILE_CREATE]     = "create",
97          [CCS_MAC_FILE_UNLINK]     = "unlink",          [CCS_MAC_FILE_UNLINK]     = "unlink",
98            [CCS_MAC_FILE_GETATTR]    = "getattr",
99          [CCS_MAC_FILE_MKDIR]      = "mkdir",          [CCS_MAC_FILE_MKDIR]      = "mkdir",
100          [CCS_MAC_FILE_RMDIR]      = "rmdir",          [CCS_MAC_FILE_RMDIR]      = "rmdir",
101          [CCS_MAC_FILE_MKFIFO]     = "mkfifo",          [CCS_MAC_FILE_MKFIFO]     = "mkfifo",
# Line 51  const char * const ccs_mac_keywords[CCS_ Line 114  const char * const ccs_mac_keywords[CCS_
114          [CCS_MAC_FILE_MOUNT]      = "mount",          [CCS_MAC_FILE_MOUNT]      = "mount",
115          [CCS_MAC_FILE_UMOUNT]     = "unmount",          [CCS_MAC_FILE_UMOUNT]     = "unmount",
116          [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",          [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",
117            /* CONFIG::misc group */
118          [CCS_MAC_ENVIRON] = "env",          [CCS_MAC_ENVIRON] = "env",
119            /* CONFIG::network group */
120          [CCS_MAC_NETWORK_INET_STREAM_BIND]       = "inet_stream_bind",          [CCS_MAC_NETWORK_INET_STREAM_BIND]       = "inet_stream_bind",
121          [CCS_MAC_NETWORK_INET_STREAM_LISTEN]     = "inet_stream_listen",          [CCS_MAC_NETWORK_INET_STREAM_LISTEN]     = "inet_stream_listen",
122          [CCS_MAC_NETWORK_INET_STREAM_CONNECT]    = "inet_stream_connect",          [CCS_MAC_NETWORK_INET_STREAM_CONNECT]    = "inet_stream_connect",
# Line 73  const char * const ccs_mac_keywords[CCS_ Line 138  const char * const ccs_mac_keywords[CCS_
138          [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN]  = "unix_seqpacket_listen",          [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN]  = "unix_seqpacket_listen",
139          [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",          [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
140          [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT]  = "unix_seqpacket_accept",          [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT]  = "unix_seqpacket_accept",
141            /* CONFIG::ipc group */
142          [CCS_MAC_SIGNAL] = "signal",          [CCS_MAC_SIGNAL] = "signal",
143            /* CONFIG::capability group */
144          [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET]  = "use_route",          [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET]  = "use_route",
145          [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",          [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",
146          [CCS_MAC_CAPABILITY_SYS_REBOOT]        = "SYS_REBOOT",          [CCS_MAC_CAPABILITY_SYS_REBOOT]        = "SYS_REBOOT",
# Line 84  const char * const ccs_mac_keywords[CCS_ Line 151  const char * const ccs_mac_keywords[CCS_
151          [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",          [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",
152          [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD]    = "SYS_KEXEC_LOAD",          [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD]    = "SYS_KEXEC_LOAD",
153          [CCS_MAC_CAPABILITY_SYS_PTRACE]        = "SYS_PTRACE",          [CCS_MAC_CAPABILITY_SYS_PTRACE]        = "SYS_PTRACE",
154            /* CONFIG group */
155          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE]       = "file",          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE]       = "file",
156          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK]    = "network",          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK]    = "network",
157          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC]       = "misc",          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC]       = "misc",
# Line 91  const char * const ccs_mac_keywords[CCS_ Line 159  const char * const ccs_mac_keywords[CCS_
159          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",          [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
160  };  };
161    
162    /* String table for path operation. */
163  const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {  const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
164          [CCS_TYPE_EXECUTE]    = "execute",          [CCS_TYPE_EXECUTE]    = "execute",
165          [CCS_TYPE_READ]       = "read",          [CCS_TYPE_READ]       = "read",
166          [CCS_TYPE_WRITE]      = "write",          [CCS_TYPE_WRITE]      = "write",
167          [CCS_TYPE_APPEND]     = "append",          [CCS_TYPE_APPEND]     = "append",
168          [CCS_TYPE_UNLINK]     = "unlink",          [CCS_TYPE_UNLINK]     = "unlink",
169            [CCS_TYPE_GETATTR]    = "getattr",
170          [CCS_TYPE_RMDIR]      = "rmdir",          [CCS_TYPE_RMDIR]      = "rmdir",
171          [CCS_TYPE_TRUNCATE]   = "truncate",          [CCS_TYPE_TRUNCATE]   = "truncate",
172          [CCS_TYPE_SYMLINK]    = "symlink",          [CCS_TYPE_SYMLINK]    = "symlink",
# Line 104  const char * const ccs_path_keyword[CCS_ Line 174  const char * const ccs_path_keyword[CCS_
174          [CCS_TYPE_UMOUNT]     = "unmount",          [CCS_TYPE_UMOUNT]     = "unmount",
175  };  };
176    
177    /* String table for socket's operation. */
178    const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
179            [CCS_NETWORK_BIND]    = "bind",
180            [CCS_NETWORK_LISTEN]  = "listen",
181            [CCS_NETWORK_CONNECT] = "connect",
182            [CCS_NETWORK_ACCEPT]  = "accept",
183            [CCS_NETWORK_SEND]    = "send",
184            [CCS_NETWORK_RECV]    = "recv",
185    };
186    
187    /* String table for categories. */
188  static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {  static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
189          [CCS_MAC_CATEGORY_FILE]       = "file",          [CCS_MAC_CATEGORY_FILE]       = "file",
190          [CCS_MAC_CATEGORY_NETWORK]    = "network",          [CCS_MAC_CATEGORY_NETWORK]    = "network",
# Line 112  static const char * const ccs_category_k Line 193  static const char * const ccs_category_k
193          [CCS_MAC_CATEGORY_CAPABILITY] = "capability",          [CCS_MAC_CATEGORY_CAPABILITY] = "capability",
194  };  };
195    
196    /* String table for conditions. */
197  const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {  const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
198          [CCS_TASK_UID]             = "task.uid",          [CCS_TASK_UID]             = "task.uid",
199          [CCS_TASK_EUID]            = "task.euid",          [CCS_TASK_EUID]            = "task.euid",
# Line 176  const char * const ccs_condition_keyword Line 258  const char * const ccs_condition_keyword
258          [CCS_PATH2_PARENT_PERM]    = "path2.parent.perm",          [CCS_PATH2_PARENT_PERM]    = "path2.parent.perm",
259  };  };
260    
261    /* String table for PREFERENCE keyword. */
262  static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {  static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
263          [CCS_PREF_MAX_GRANT_LOG]      = "max_grant_log",          [CCS_PREF_MAX_AUDIT_LOG]      = "max_audit_log",
         [CCS_PREF_MAX_REJECT_LOG]     = "max_reject_log",  
264          [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",          [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
265          [CCS_PREF_ENFORCING_PENALTY]  = "enforcing_penalty",          [CCS_PREF_ENFORCING_PENALTY]  = "enforcing_penalty",
266  };  };
# Line 190  static bool ccs_manage_by_non_root; Line 272  static bool ccs_manage_by_non_root;
272   * ccs_yesno - Return "yes" or "no".   * ccs_yesno - Return "yes" or "no".
273   *   *
274   * @value: Bool value.   * @value: Bool value.
275     *
276     * Returns "yes" if @value is not 0, "no" otherwise.
277   */   */
278  static const char *ccs_yesno(const unsigned int value)  const char *ccs_yesno(const unsigned int value)
279  {  {
280          return value ? "yes" : "no";          return value ? "yes" : "no";
281  }  }
282    
283    /* Prototype for ccs_addprintf(). */
284  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
285       __attribute__ ((format(printf, 3, 4)));          __attribute__ ((format(printf, 3, 4)));
286    
287    /**
288     * ccs_addprintf - strncat()-like-snprintf().
289     *
290     * @buffer: Buffer to write to. Must be '\0'-terminated.
291     * @len:    Size of @buffer.
292     * @fmt:    The printf()'s format string, followed by parameters.
293     *
294     * Returns nothing.
295     */
296  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
297  {  {
298          va_list args;          va_list args;
# Line 211  static void ccs_addprintf(char *buffer, Line 305  static void ccs_addprintf(char *buffer,
305  /**  /**
306   * ccs_flush - Flush queued string to userspace's buffer.   * ccs_flush - Flush queued string to userspace's buffer.
307   *   *
308   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
309   *   *
310   * Returns true if all data was flushed, false otherwise.   * Returns true if all data was flushed, false otherwise.
311   */   */
# Line 219  static bool ccs_flush(struct ccs_io_buff Line 313  static bool ccs_flush(struct ccs_io_buff
313  {  {
314          while (head->r.w_pos) {          while (head->r.w_pos) {
315                  const char *w = head->r.w[0];                  const char *w = head->r.w[0];
316                  int len = strlen(w);                  size_t len = strlen(w);
317                  if (len) {                  if (len) {
318                          if (len > head->read_user_buf_avail)                          if (len > head->read_user_buf_avail)
319                                  len = head->read_user_buf_avail;                                  len = head->read_user_buf_avail;
# Line 231  static bool ccs_flush(struct ccs_io_buff Line 325  static bool ccs_flush(struct ccs_io_buff
325                          head->read_user_buf += len;                          head->read_user_buf += len;
326                          w += len;                          w += len;
327                  }                  }
328                  if (*w) {                  head->r.w[0] = w;
329                          head->r.w[0] = w;                  if (*w)
330                          return false;                          return false;
                 }  
331                  /* Add '\0' for audit logs and query. */                  /* Add '\0' for audit logs and query. */
332                  if (head->poll) {                  if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
333                          if (!head->read_user_buf_avail ||                          if (!head->read_user_buf_avail ||
334                              copy_to_user(head->read_user_buf, "", 1))                              copy_to_user(head->read_user_buf, "", 1))
335                                  return false;                                  return false;
# Line 257  static bool ccs_flush(struct ccs_io_buff Line 350  static bool ccs_flush(struct ccs_io_buff
350   * @head:   Pointer to "struct ccs_io_buffer".   * @head:   Pointer to "struct ccs_io_buffer".
351   * @string: String to print.   * @string: String to print.
352   *   *
353     * Returns nothing.
354     *
355   * Note that @string has to be kept valid until @head is kfree()d.   * Note that @string has to be kept valid until @head is kfree()d.
356   * This means that char[] allocated on stack memory cannot be passed to   * This means that char[] allocated on stack memory cannot be passed to
357   * this function. Use ccs_io_printf() for char[] allocated on stack memory.   * this function. Use ccs_io_printf() for char[] allocated on stack memory.
# Line 270  static void ccs_set_string(struct ccs_io Line 365  static void ccs_set_string(struct ccs_io
365                  printk(KERN_WARNING "Too many words in a line.\n");                  printk(KERN_WARNING "Too many words in a line.\n");
366  }  }
367    
368    /* Prototype for ccs_io_printf(). */
369    static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
370            __attribute__ ((format(printf, 2, 3)));
371    
372  /**  /**
373   * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.   * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
374   *   *
375   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
376   * @fmt:  The printf()'s format string, followed by parameters.   * @fmt:  The printf()'s format string, followed by parameters.
377     *
378     * Returns nothing.
379   */   */
380  void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)  static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
381  {  {
382          va_list args;          va_list args;
383          int len;          size_t len;
384          int pos = head->r.avail;          size_t pos = head->r.avail;
385          int size = head->readbuf_size - pos;          int size = head->readbuf_size - pos;
386          if (size <= 0)          if (size <= 0)
387                  return;                  return;
# Line 295  void ccs_io_printf(struct ccs_io_buffer Line 396  void ccs_io_printf(struct ccs_io_buffer
396          ccs_set_string(head, head->read_buf + pos);          ccs_set_string(head, head->read_buf + pos);
397  }  }
398    
399    /**
400     * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
401     *
402     * @head: Pointer to "struct ccs_io_buffer".
403     *
404     * Returns nothing.
405     */
406  static void ccs_set_space(struct ccs_io_buffer *head)  static void ccs_set_space(struct ccs_io_buffer *head)
407  {  {
408          ccs_set_string(head, " ");          ccs_set_string(head, " ");
409  }  }
410    
411    /**
412     * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
413     *
414     * @head: Pointer to "struct ccs_io_buffer".
415     *
416     * Returns nothing.
417     */
418  static bool ccs_set_lf(struct ccs_io_buffer *head)  static bool ccs_set_lf(struct ccs_io_buffer *head)
419  {  {
420          ccs_set_string(head, "\n");          ccs_set_string(head, "\n");
# Line 307  static bool ccs_set_lf(struct ccs_io_buf Line 422  static bool ccs_set_lf(struct ccs_io_buf
422  }  }
423    
424  /**  /**
425     * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
426     *
427     * @head: Pointer to "struct ccs_io_buffer".
428     *
429     * Returns nothing.
430     */
431    static void ccs_set_slash(struct ccs_io_buffer *head)
432    {
433            ccs_set_string(head, "/");
434    }
435    
436    /* List of namespaces. */
437    LIST_HEAD(ccs_namespace_list);
438    /* True if namespace other than ccs_kernel_namespace is defined. */
439    static bool ccs_namespace_enabled;
440    
441    /**
442     * ccs_init_policy_namespace - Initialize namespace.
443     *
444     * @ns: Pointer to "struct ccs_policy_namespace".
445     *
446     * Returns nothing.
447     */
448    void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
449    {
450            unsigned int idx;
451            for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
452                    INIT_LIST_HEAD(&ns->acl_group[idx]);
453            for (idx = 0; idx < CCS_MAX_GROUP; idx++)
454                    INIT_LIST_HEAD(&ns->group_list[idx]);
455            for (idx = 0; idx < CCS_MAX_POLICY; idx++)
456                    INIT_LIST_HEAD(&ns->policy_list[idx]);
457            ns->profile_version = 20100903;
458            ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
459            list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
460    }
461    
462    /**
463     * ccs_print_namespace - Print namespace header.
464     *
465     * @head: Pointer to "struct ccs_io_buffer".
466     *
467     * Returns nothing.
468     */
469    static void ccs_print_namespace(struct ccs_io_buffer *head)
470    {
471            if (!ccs_namespace_enabled)
472                    return;
473            ccs_set_string(head,
474                           container_of(head->r.ns, struct ccs_policy_namespace,
475                                        namespace_list)->name);
476            ccs_set_space(head);
477    }
478    
479    /**
480   * ccs_assign_profile - Create a new profile.   * ccs_assign_profile - Create a new profile.
481   *   *
482     * @ns:      Pointer to "struct ccs_policy_namespace".
483   * @profile: Profile number to create.   * @profile: Profile number to create.
484   *   *
485   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
486   */   */
487  static struct ccs_profile *ccs_assign_profile(const unsigned int profile)  static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
488                                                  const unsigned int profile)
489  {  {
490          struct ccs_profile *ptr;          struct ccs_profile *ptr;
491          struct ccs_profile *entry;          struct ccs_profile *entry;
492          if (profile >= CCS_MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
493                  return NULL;                  return NULL;
494          ptr = ccs_profile_ptr[profile];          ptr = ns->profile_ptr[profile];
495          if (ptr)          if (ptr)
496                  return ptr;                  return ptr;
497          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
498          if (mutex_lock_interruptible(&ccs_policy_lock))          if (mutex_lock_interruptible(&ccs_policy_lock))
499                  goto out;                  goto out;
500          ptr = ccs_profile_ptr[profile];          ptr = ns->profile_ptr[profile];
501          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
502                  ptr = entry;                  ptr = entry;
503                  ptr->default_config = CCS_CONFIG_DISABLED |                  ptr->default_config = CCS_CONFIG_DISABLED |
504                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
505                  memset(ptr->config, CCS_CONFIG_USE_DEFAULT,                  memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
506                         sizeof(ptr->config));                         sizeof(ptr->config));
507                  ptr->pref[CCS_PREF_MAX_GRANT_LOG] =                  ptr->pref[CCS_PREF_MAX_AUDIT_LOG] =
508                          CONFIG_CCSECURITY_MAX_GRANT_LOG;                          CONFIG_CCSECURITY_MAX_AUDIT_LOG;
                 ptr->pref[CCS_PREF_MAX_REJECT_LOG] =  
                         CONFIG_CCSECURITY_MAX_REJECT_LOG;  
509                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
510                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
511                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
512                  ccs_profile_ptr[profile] = ptr;                  ns->profile_ptr[profile] = ptr;
513                  entry = NULL;                  entry = NULL;
514          }          }
515          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
# Line 350  out: Line 520  out:
520    
521  /**  /**
522   * ccs_check_profile - Check all profiles currently assigned to domains are defined.   * ccs_check_profile - Check all profiles currently assigned to domains are defined.
523     *
524     * Returns nothing.
525   */   */
526  static void ccs_check_profile(void)  static void ccs_check_profile(void)
527  {  {
528          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
529          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
530          ccs_policy_loaded = true;          ccs_policy_loaded = true;
531            printk(KERN_INFO "CCSecurity: 1.8.3   2011/09/29\n");
532          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
533                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
534                  if (ccs_profile_ptr[profile])                  const struct ccs_policy_namespace *ns = domain->ns;
535                    if (ns->profile_version != 20100903)
536                            printk(KERN_ERR
537                                   "Profile version %u is not supported.\n",
538                                   ns->profile_version);
539                    else if (!ns->profile_ptr[profile])
540                            printk(KERN_ERR
541                                   "Profile %u (used by '%s') is not defined.\n",
542                                   profile, domain->domainname->name);
543                    else
544                          continue;                          continue;
545                  printk(KERN_ERR "You need to define profile %u before using it.\n",                  printk(KERN_ERR
546                         profile);                         "Userland tools for TOMOYO 1.8 must be installed and "
547                           "policy must be initialized.\n");
548                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
549                         "for more information.\n");                         "for more information.\n");
550                  panic("Profile %u (used by '%s') not defined.\n",                  panic("STOP!");
                       profile, domain->domainname->name);  
551          }          }
552          ccs_read_unlock(idx);          ccs_read_unlock(idx);
         if (ccs_profile_version != 20100903) {  
                 printk(KERN_ERR "You need to install userland programs for "  
                        "TOMOYO 1.8 and initialize policy configuration.\n");  
                 printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "  
                        "for more information.\n");  
                 panic("Profile version %u is not supported.\n",  
                       ccs_profile_version);  
         }  
         printk(KERN_INFO "CCSecurity: 1.8.0-pre   2010/10/10\n");  
553          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
554  }  }
555    
# Line 390  static void ccs_check_profile(void) Line 563  static void ccs_check_profile(void)
563  struct ccs_profile *ccs_profile(const u8 profile)  struct ccs_profile *ccs_profile(const u8 profile)
564  {  {
565          static struct ccs_profile ccs_null_profile;          static struct ccs_profile ccs_null_profile;
566          struct ccs_profile *ptr = ccs_profile_ptr[profile];          struct ccs_profile *ptr = ccs_current_namespace()->
567                    profile_ptr[profile];
568          if (!ptr)          if (!ptr)
569                  ptr = &ccs_null_profile;                  ptr = &ccs_null_profile;
570          return ptr;          return ptr;
571  }  }
572    
573    /**
574     * ccs_find_yesno - Find values for specified keyword.
575     *
576     * @string: String to check.
577     * @find:   Name of keyword.
578     *
579     * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
580     */
581  static s8 ccs_find_yesno(const char *string, const char *find)  static s8 ccs_find_yesno(const char *string, const char *find)
582  {  {
583          const char *cp = strstr(string, find);          const char *cp = strstr(string, find);
# Line 409  static s8 ccs_find_yesno(const char *str Line 591  static s8 ccs_find_yesno(const char *str
591          return -1;          return -1;
592  }  }
593    
594    /**
595     * ccs_set_uint - Set value for specified preference.
596     *
597     * @i:      Pointer to "unsigned int".
598     * @string: String to check.
599     * @find:   Name of keyword.
600     *
601     * Returns nothing.
602     */
603  static void ccs_set_uint(unsigned int *i, const char *string, const char *find)  static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
604  {  {
605          const char *cp = strstr(string, find);          const char *cp = strstr(string, find);
# Line 416  static void ccs_set_uint(unsigned int *i Line 607  static void ccs_set_uint(unsigned int *i
607                  sscanf(cp + strlen(find), "=%u", i);                  sscanf(cp + strlen(find), "=%u", i);
608  }  }
609    
610    /**
611     * ccs_set_mode - Set mode for specified profile.
612     *
613     * @name:    Name of functionality.
614     * @value:   Mode for @name.
615     * @profile: Pointer to "struct ccs_profile".
616     *
617     * Returns 0 on success, negative value otherwise.
618     */
619  static int ccs_set_mode(char *name, const char *value,  static int ccs_set_mode(char *name, const char *value,
620                          struct ccs_profile *profile)                          struct ccs_profile *profile)
621  {  {
# Line 498  static int ccs_write_profile(struct ccs_ Line 698  static int ccs_write_profile(struct ccs_
698          unsigned int i;          unsigned int i;
699          char *cp;          char *cp;
700          struct ccs_profile *profile;          struct ccs_profile *profile;
701          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)          if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
702                == 1)
703                  return 0;                  return 0;
704          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
705          if (*cp != '-')          if (*cp != '-')
706                  return -EINVAL;                  return -EINVAL;
707          data = cp + 1;          data = cp + 1;
708          profile = ccs_assign_profile(i);          profile = ccs_assign_profile(head->w.ns, i);
709          if (!profile)          if (!profile)
710                  return -EINVAL;                  return -EINVAL;
711          cp = strchr(data, '=');          cp = strchr(data, '=');
# Line 512  static int ccs_write_profile(struct ccs_ Line 713  static int ccs_write_profile(struct ccs_
713                  return -EINVAL;                  return -EINVAL;
714          *cp++ = '\0';          *cp++ = '\0';
715          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
716                  const struct ccs_path_info *old_comment = profile->comment;                  static DEFINE_SPINLOCK(lock);
717                  profile->comment = ccs_get_name(cp);                  const struct ccs_path_info *new_comment = ccs_get_name(cp);
718                    const struct ccs_path_info *old_comment;
719                    if (!new_comment)
720                            return -ENOMEM;
721                    spin_lock(&lock);
722                    old_comment = profile->comment;
723                    profile->comment = new_comment;
724                    spin_unlock(&lock);
725                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
726                  return 0;                  return 0;
727          }          }
# Line 526  static int ccs_write_profile(struct ccs_ Line 734  static int ccs_write_profile(struct ccs_
734          return ccs_set_mode(data, cp, profile);          return ccs_set_mode(data, cp, profile);
735  }  }
736    
737    /**
738     * ccs_print_config - Print mode for specified functionality.
739     *
740     * @head:   Pointer to "struct ccs_io_buffer".
741     * @config: Mode for that functionality.
742     *
743     * Returns nothing.
744     *
745     * Caller prints functionality's name.
746     */
747  static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)  static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
748  {  {
749          ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",          ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
# Line 538  static void ccs_print_config(struct ccs_ Line 756  static void ccs_print_config(struct ccs_
756   * ccs_read_profile - Read profile table.   * ccs_read_profile - Read profile table.
757   *   *
758   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
759     *
760     * Returns nothing.
761   */   */
762  static void ccs_read_profile(struct ccs_io_buffer *head)  static void ccs_read_profile(struct ccs_io_buffer *head)
763  {  {
764          u8 index;          u8 index;
765            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
766                                                           namespace_list);
767          const struct ccs_profile *profile;          const struct ccs_profile *profile;
768            if (head->r.eof)
769                    return;
770  next:  next:
771          index = head->r.index;          index = head->r.index;
772          profile = ccs_profile_ptr[index];          profile = ns->profile_ptr[index];
773          switch (head->r.step) {          switch (head->r.step) {
774          case 0:          case 0:
775                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");                  ccs_print_namespace(head);
776                    ccs_io_printf(head, "PROFILE_VERSION=%u\n",
777                                  ns->profile_version);
778                  head->r.step++;                  head->r.step++;
779                  break;                  break;
780          case 1:          case 1:
781                  for ( ; head->r.index < CCS_MAX_PROFILES;                  for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
782                        head->r.index++)                          if (ns->profile_ptr[head->r.index])
                         if (ccs_profile_ptr[head->r.index])  
783                                  break;                                  break;
784                  if (head->r.index == CCS_MAX_PROFILES)                  if (head->r.index == CCS_MAX_PROFILES) {
785                            head->r.eof = true;
786                          return;                          return;
787                    }
788                  head->r.step++;                  head->r.step++;
789                  break;                  break;
790          case 2:          case 2:
791                  {                  {
792                          u8 i;                          u8 i;
793                          const struct ccs_path_info *comment = profile->comment;                          const struct ccs_path_info *comment = profile->comment;
794                            ccs_print_namespace(head);
795                          ccs_io_printf(head, "%u-COMMENT=", index);                          ccs_io_printf(head, "%u-COMMENT=", index);
796                          ccs_set_string(head, comment ? comment->name : "");                          ccs_set_string(head, comment ? comment->name : "");
797                          ccs_set_lf(head);                          ccs_set_lf(head);
798                            ccs_print_namespace(head);
799                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);
800                          for (i = 0; i < CCS_MAX_PREF; i++)                          for (i = 0; i < CCS_MAX_PREF; i++)
801                                  ccs_io_printf(head, "%s=%u ",                                  ccs_io_printf(head, "%s=%u ",
802                                                ccs_pref_keywords[i],                                                ccs_pref_keywords[i],
803                                                profile->pref[i]);                                                profile->pref[i]);
804                          ccs_set_string(head, " }\n");                          ccs_set_string(head, "}\n");
805                          head->r.step++;                          head->r.step++;
806                  }                  }
807                  break;                  break;
808          case 3:          case 3:
809                  {                  {
810                            ccs_print_namespace(head);
811                          ccs_io_printf(head, "%u-%s", index, "CONFIG");                          ccs_io_printf(head, "%u-%s", index, "CONFIG");
812                          ccs_print_config(head, profile->default_config);                          ccs_print_config(head, profile->default_config);
813                          head->r.bit = 0;                          head->r.bit = 0;
# Line 591  next: Line 821  next:
821                          const u8 config = profile->config[i];                          const u8 config = profile->config[i];
822                          if (config == CCS_CONFIG_USE_DEFAULT)                          if (config == CCS_CONFIG_USE_DEFAULT)
823                                  continue;                                  continue;
824                            ccs_print_namespace(head);
825                          if (i < CCS_MAX_MAC_INDEX)                          if (i < CCS_MAX_MAC_INDEX)
826                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
827                                                ccs_category_keywords                                                ccs_category_keywords
# Line 614  next: Line 845  next:
845                  goto next;                  goto next;
846  }  }
847    
848    /**
849     * ccs_same_manager - Check for duplicated "struct ccs_manager" entry.
850     *
851     * @a: Pointer to "struct ccs_acl_head".
852     * @b: Pointer to "struct ccs_acl_head".
853     *
854     * Returns true if @a == @b, false otherwise.
855     */
856  static bool ccs_same_manager(const struct ccs_acl_head *a,  static bool ccs_same_manager(const struct ccs_acl_head *a,
857                               const struct ccs_acl_head *b)                               const struct ccs_acl_head *b)
858  {  {
# Line 629  static bool ccs_same_manager(const struc Line 868  static bool ccs_same_manager(const struc
868   *   *
869   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
870   */   */
871  static int ccs_update_manager_entry(const char *manager, const bool is_delete)  static inline int ccs_update_manager_entry(const char *manager,
872                                               const bool is_delete)
873  {  {
874          struct ccs_manager e = { };          struct ccs_manager e = { };
875            struct ccs_acl_param param = {
876                    /* .ns = &ccs_kernel_namespace, */
877                    .is_delete = is_delete,
878                    .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
879            };
880          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
881          if (ccs_domain_def(manager)) {          if (ccs_domain_def(manager)) {
882                  if (!ccs_correct_domain(manager))                  if (!ccs_correct_domain(manager))
# Line 642  static int ccs_update_manager_entry(cons Line 887  static int ccs_update_manager_entry(cons
887                          return -EINVAL;                          return -EINVAL;
888          }          }
889          e.manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
890          if (!e.manager)          if (e.manager) {
891                  return error;                  error = ccs_update_policy(&e.head, sizeof(e), &param,
892          error = ccs_update_policy(&e.head, sizeof(e), is_delete,                                            ccs_same_manager);
893                                    &ccs_policy_list[CCS_ID_MANAGER],                  ccs_put_name(e.manager);
894                                    ccs_same_manager);          }
         ccs_put_name(e.manager);  
895          return error;          return error;
896  }  }
897    
# Line 660  static int ccs_update_manager_entry(cons Line 904  static int ccs_update_manager_entry(cons
904   */   */
905  static int ccs_write_manager(struct ccs_io_buffer *head)  static int ccs_write_manager(struct ccs_io_buffer *head)
906  {  {
907          char *data = head->write_buf;          const char *data = head->write_buf;
         bool is_delete = ccs_str_starts(&data, "delete ");  
908          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
909                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !head->w.is_delete;
910                  return 0;                  return 0;
911          }          }
912          return ccs_update_manager_entry(data, is_delete);          return ccs_update_manager_entry(data, head->w.is_delete);
913  }  }
914    
915  /**  /**
# Line 674  static int ccs_write_manager(struct ccs_ Line 917  static int ccs_write_manager(struct ccs_
917   *   *
918   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
919   *   *
920     * Returns nothing.
921     *
922   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
923   */   */
924  static void ccs_read_manager(struct ccs_io_buffer *head)  static void ccs_read_manager(struct ccs_io_buffer *head)
925  {  {
926          if (head->r.eof)          if (head->r.eof)
927                  return;                  return;
928          list_for_each_cookie(head->r.acl, &ccs_policy_list[CCS_ID_MANAGER]) {          list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
929                                 policy_list[CCS_ID_MANAGER]) {
930                  struct ccs_manager *ptr =                  struct ccs_manager *ptr =
931                          list_entry(head->r.acl, typeof(*ptr), head.list);                          list_entry(head->r.acl, typeof(*ptr), head.list);
932                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
# Line 716  static bool ccs_manager(void) Line 962  static bool ccs_manager(void)
962          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
963                  return false;                  return false;
964          exe = ccs_get_exe();          exe = ccs_get_exe();
965          list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
966                                   head.list, &ccs_ss) {                                   policy_list[CCS_ID_MANAGER], head.list,
967                                     &ccs_ss) {
968                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
969                          continue;                          continue;
970                  if (ptr->is_domain) {                  if (ptr->is_domain) {
# Line 746  static bool ccs_manager(void) Line 993  static bool ccs_manager(void)
993  }  }
994    
995  /**  /**
996   * ccs_select_one - Parse select command.   * ccs_select_domain - Parse select command.
997   *   *
998   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
999   * @data: String to parse.   * @data: String to parse.
# Line 755  static bool ccs_manager(void) Line 1002  static bool ccs_manager(void)
1002   *   *
1003   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1004   */   */
1005  static bool ccs_select_one(struct ccs_io_buffer *head, const char *data)  static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
1006  {  {
1007          unsigned int pid;          unsigned int pid;
1008          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1009          bool global_pid = false;          bool global_pid = false;
1010          if (!strcmp(data, "execute")) {          if (strncmp(data, "select ", 7))
1011                  head->r.print_execute_only = true;                  return false;
1012                  return true;          data += 7;
         }  
1013          if (sscanf(data, "pid=%u", &pid) == 1 ||          if (sscanf(data, "pid=%u", &pid) == 1 ||
1014              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
1015                  struct task_struct *p;                  struct task_struct *p;
# Line 781  static bool ccs_select_one(struct ccs_io Line 1027  static bool ccs_select_one(struct ccs_io
1027                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
1028                  ccs_tasklist_unlock();                  ccs_tasklist_unlock();
1029          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
1030                  if (ccs_domain_def(data + 7))                  if (*(data + 7) == '<')
1031                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
1032          } else          } else
1033                  return false;                  return false;
# Line 801  static bool ccs_select_one(struct ccs_io Line 1047  static bool ccs_select_one(struct ccs_io
1047          return true;          return true;
1048  }  }
1049    
1050    /**
1051     * ccs_same_handler_acl - Check for duplicated "struct ccs_handler_acl" entry.
1052     *
1053     * @a: Pointer to "struct ccs_acl_info".
1054     * @b: Pointer to "struct ccs_acl_info".
1055     *
1056     * Returns true if @a == @b, false otherwise.
1057     */
1058  static bool ccs_same_handler_acl(const struct ccs_acl_info *a,  static bool ccs_same_handler_acl(const struct ccs_acl_info *a,
1059                                   const struct ccs_acl_info *b)                                   const struct ccs_acl_info *b)
1060  {  {
# Line 809  static bool ccs_same_handler_acl(const s Line 1063  static bool ccs_same_handler_acl(const s
1063          return p1->handler == p2->handler;          return p1->handler == p2->handler;
1064  }  }
1065    
1066    /**
1067     * ccs_same_task_acl - Check for duplicated "struct ccs_task_acl" entry.
1068     *
1069     * @a: Pointer to "struct ccs_acl_info".
1070     * @b: Pointer to "struct ccs_acl_info".
1071     *
1072     * Returns true if @a == @b, false otherwise.
1073     */
1074  static bool ccs_same_task_acl(const struct ccs_acl_info *a,  static bool ccs_same_task_acl(const struct ccs_acl_info *a,
1075                                const struct ccs_acl_info *b)                                const struct ccs_acl_info *b)
1076  {  {
# Line 823  static bool ccs_same_task_acl(const stru Line 1085  static bool ccs_same_task_acl(const stru
1085   * @param: Pointer to "struct ccs_acl_param".   * @param: Pointer to "struct ccs_acl_param".
1086   *   *
1087   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1088     *
1089     * Caller holds ccs_read_lock().
1090   */   */
1091  static int ccs_write_task(struct ccs_acl_param *param)  static int ccs_write_task(struct ccs_acl_param *param)
1092  {  {
# Line 868  static int ccs_write_task(struct ccs_acl Line 1132  static int ccs_write_task(struct ccs_acl
1132          return error;          return error;
1133  }  }
1134    
1135  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  /**
1136     * ccs_write_domain2 - Write domain policy.
1137     *
1138     * @ns:        Pointer to "struct ccs_policy_namespace".
1139     * @list:      Pointer to "struct list_head".
1140     * @data:      Policy to be interpreted.
1141     * @is_delete: True if it is a delete request.
1142     *
1143     * Returns 0 on success, negative value otherwise.
1144     *
1145     * Caller holds ccs_read_lock().
1146     */
1147    static int ccs_write_domain2(struct ccs_policy_namespace *ns,
1148                                 struct list_head *list, char *data,
1149                               const bool is_delete)                               const bool is_delete)
1150  {  {
1151          struct ccs_acl_param param = {          struct ccs_acl_param param = {
1152                    .ns = ns,
1153                    .list = list,
1154                  .data = data,                  .data = data,
                 .domain = domain,  
1155                  .is_delete = is_delete,                  .is_delete = is_delete,
1156          };          };
1157          static const struct {          static const struct {
# Line 885  static int ccs_write_domain2(char *data, Line 1163  static int ccs_write_domain2(char *data,
1163                  { "network unix ", ccs_write_unix_network },                  { "network unix ", ccs_write_unix_network },
1164                  { "misc ", ccs_write_misc },                  { "misc ", ccs_write_misc },
1165                  { "capability ", ccs_write_capability },                  { "capability ", ccs_write_capability },
1166                  { "ipc ", ccs_write_ipc },                  { "ipc signal ", ccs_write_ipc },
1167                  { "task ", ccs_write_task },                  { "task ", ccs_write_task },
1168          };          };
1169          u8 i;          u8 i;
1170          for (i = 0; i < 7; i++) {          for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
1171                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
1172                          continue;                          continue;
1173                  return ccs_callback[i].write(&param);                  return ccs_callback[i].write(&param);
# Line 897  static int ccs_write_domain2(char *data, Line 1175  static int ccs_write_domain2(char *data,
1175          return -EINVAL;          return -EINVAL;
1176  }  }
1177    
1178    /**
1179     * ccs_delete_domain - Delete a domain.
1180     *
1181     * @domainname: The name of domain.
1182     *
1183     * Returns 0.
1184     */
1185    static int ccs_delete_domain(char *domainname)
1186    {
1187            struct ccs_domain_info *domain;
1188            struct ccs_path_info name;
1189            name.name = domainname;
1190            ccs_fill_path_info(&name);
1191            if (mutex_lock_interruptible(&ccs_policy_lock))
1192                    return 0;
1193            /* Is there an active domain? */
1194            list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
1195                    /* Never delete ccs_kernel_domain. */
1196                    if (domain == &ccs_kernel_domain)
1197                            continue;
1198                    if (domain->is_deleted ||
1199                        ccs_pathcmp(domain->domainname, &name))
1200                            continue;
1201                    domain->is_deleted = true;
1202                    break;
1203            }
1204            mutex_unlock(&ccs_policy_lock);
1205            return 0;
1206    }
1207    
1208    /* String table for domain flags. */
1209  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1210          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",
1211          [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",          [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",
# Line 908  const char * const ccs_dif[CCS_MAX_DOMAI Line 1217  const char * const ccs_dif[CCS_MAX_DOMAI
1217   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1218   *   *
1219   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1220     *
1221     * Caller holds ccs_read_lock().
1222   */   */
1223  static int ccs_write_domain(struct ccs_io_buffer *head)  static int ccs_write_domain(struct ccs_io_buffer *head)
1224  {  {
1225          char *data = head->write_buf;          char *data = head->write_buf;
1226            struct ccs_policy_namespace *ns;
1227          struct ccs_domain_info *domain = head->w.domain;          struct ccs_domain_info *domain = head->w.domain;
1228          bool is_delete = false;          const bool is_delete = head->w.is_delete;
1229          bool is_select = false;          const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
1230          unsigned int profile;          unsigned int profile;
1231          if (ccs_str_starts(&data, "delete "))          if (*data == '<') {
                 is_delete = true;  
         else if (ccs_str_starts(&data, "select "))  
                 is_select = true;  
         if (is_select && ccs_select_one(head, data))  
                 return 0;  
         /* Don't allow updating policies by non manager programs. */  
         if (!ccs_manager())  
                 return -EPERM;  
         if (ccs_domain_def(data)) {  
1232                  domain = NULL;                  domain = NULL;
1233                  if (is_delete)                  if (is_delete)
1234                          ccs_delete_domain(data);                          ccs_delete_domain(data);
1235                  else if (is_select)                  else if (is_select)
1236                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
1237                  else                  else
1238                          domain = ccs_assign_domain(data, 0, 0, false);                          domain = ccs_assign_domain(data, false);
1239                  head->w.domain = domain;                  head->w.domain = domain;
1240                  return 0;                  return 0;
1241          }          }
1242          if (!domain)          if (!domain)
1243                  return -EINVAL;                  return -EINVAL;
1244            ns = domain->ns;
1245          if (sscanf(data, "use_profile %u\n", &profile) == 1          if (sscanf(data, "use_profile %u\n", &profile) == 1
1246              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
1247                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])                  if (!ccs_policy_loaded || ns->profile_ptr[(u8) profile])
1248                          domain->profile = (u8) profile;                          if (!is_delete)
1249                                    domain->profile = (u8) profile;
1250                  return 0;                  return 0;
1251          }          }
1252          if (sscanf(data, "use_group %u\n", &profile) == 1          if (sscanf(data, "use_group %u\n", &profile) == 1
1253              && profile < CCS_MAX_ACL_GROUPS) {              && profile < CCS_MAX_ACL_GROUPS) {
1254                  domain->group = (u8) profile;                  if (!is_delete)
1255                            domain->group = (u8) profile;
1256                  return 0;                  return 0;
1257          }          }
1258          for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {          for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {
# Line 957  static int ccs_write_domain(struct ccs_i Line 1262  static int ccs_write_domain(struct ccs_i
1262                  domain->flags[profile] = !is_delete;                  domain->flags[profile] = !is_delete;
1263                  return 0;                  return 0;
1264          }          }
1265          return ccs_write_domain2(data, domain, is_delete);          return ccs_write_domain2(ns, &domain->acl_info_list, data, is_delete);
1266  }  }
1267    
1268  /**  /**
# Line 965  static int ccs_write_domain(struct ccs_i Line 1270  static int ccs_write_domain(struct ccs_i
1270   *   *
1271   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1272   * @ptr:  Pointer to "struct ccs_name_union".   * @ptr:  Pointer to "struct ccs_name_union".
1273     *
1274     * Returns nothing.
1275   */   */
1276  static void ccs_print_name_union(struct ccs_io_buffer *head,  static void ccs_print_name_union(struct ccs_io_buffer *head,
1277                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
1278  {  {
1279          const bool cond = head->r.print_cond_part;          ccs_set_space(head);
1280          if (!cond)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1281                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1282                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1283          } else {          } else {
                 if (cond)  
                         ccs_set_string(head, "\"");  
1284                  ccs_set_string(head, ptr->filename->name);                  ccs_set_string(head, ptr->filename->name);
                 if (cond)  
                         ccs_set_string(head, "\"");  
1285          }          }
1286  }  }
1287    
1288  /**  /**
1289   * ccs_print_number_union - Print a ccs_number_union.   * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
1290     *
1291     * @head: Pointer to "struct ccs_io_buffer".
1292     * @ptr:  Pointer to "struct ccs_name_union".
1293     *
1294     * Returns nothing.
1295     */
1296    static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
1297                                            const struct ccs_name_union *ptr)
1298    {
1299            if (ptr->group) {
1300                    ccs_set_string(head, "@");
1301                    ccs_set_string(head, ptr->group->group_name->name);
1302            } else {
1303                    ccs_set_string(head, "\"");
1304                    ccs_set_string(head, ptr->filename->name);
1305                    ccs_set_string(head, "\"");
1306            }
1307    }
1308    
1309    /**
1310     * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
1311   *   *
1312   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1313   * @ptr:  Pointer to "struct ccs_number_union".   * @ptr:  Pointer to "struct ccs_number_union".
1314     *
1315     * Returns nothing.
1316   */   */
1317  static void ccs_print_number_union(struct ccs_io_buffer *head,  static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1318                                     const struct ccs_number_union *ptr)                                             const struct ccs_number_union *ptr)
1319  {  {
1320          if (!head->r.print_cond_part)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1321                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1322                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1323          } else {          } else {
# Line 1032  static void ccs_print_number_union(struc Line 1354  static void ccs_print_number_union(struc
1354  }  }
1355    
1356  /**  /**
1357     * ccs_print_number_union - Print a ccs_number_union.
1358     *
1359     * @head: Pointer to "struct ccs_io_buffer".
1360     * @ptr:  Pointer to "struct ccs_number_union".
1361     *
1362     * Returns nothing.
1363     */
1364    static void ccs_print_number_union(struct ccs_io_buffer *head,
1365                                       const struct ccs_number_union *ptr)
1366    {
1367            ccs_set_space(head);
1368            ccs_print_number_union_nospace(head, ptr);
1369    }
1370    
1371    /**
1372   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1373   *   *
1374   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1046  static bool ccs_print_condition(struct c Line 1383  static bool ccs_print_condition(struct c
1383          case 0:          case 0:
1384                  head->r.cond_index = 0;                  head->r.cond_index = 0;
1385                  head->r.cond_step++;                  head->r.cond_step++;
1386                    if (cond->transit && cond->exec_transit) {
1387                            ccs_set_space(head);
1388                            ccs_set_string(head, cond->transit->name);
1389                    }
1390                  /* fall through */                  /* fall through */
1391          case 1:          case 1:
1392                  {                  {
# Line 1098  static bool ccs_print_condition(struct c Line 1439  static bool ccs_print_condition(struct c
1439                                  switch (left) {                                  switch (left) {
1440                                  case CCS_ARGV_ENTRY:                                  case CCS_ARGV_ENTRY:
1441                                          ccs_io_printf(head,                                          ccs_io_printf(head,
1442                                                        "exec.argv[%u]%s\"%s\"",                                                        "exec.argv[%lu]%s=\"",
1443                                                        argv->index,                                                        argv->index,
1444                                                        argv->is_not ?                                                        argv->is_not ? "!" : "");
1445                                                        "!=" : "=",                                          ccs_set_string(head,
1446                                                        argv->value->name);                                                         argv->value->name);
1447                                            ccs_set_string(head, "\"");
1448                                          argv++;                                          argv++;
1449                                          continue;                                          continue;
1450                                  case CCS_ENVP_ENTRY:                                  case CCS_ENVP_ENTRY:
1451                                          ccs_io_printf(head,                                          ccs_set_string(head, "exec.envp[\"");
1452                                                        "exec.envp[\"%s\"]%s",                                          ccs_set_string(head, envp->name->name);
1453                                                        envp->name->name,                                          ccs_io_printf(head, "\"]%s=",
1454                                                        envp->is_not ?                                                        envp->is_not ? "!" : "");
                                                       "!=" : "=");  
1455                                          if (envp->value) {                                          if (envp->value) {
1456                                                  ccs_set_string(head, "\"");                                                  ccs_set_string(head, "\"");
1457                                                  ccs_set_string(head, envp->                                                  ccs_set_string(head, envp->
# Line 1122  static bool ccs_print_condition(struct c Line 1463  static bool ccs_print_condition(struct c
1463                                          envp++;                                          envp++;
1464                                          continue;                                          continue;
1465                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1466                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1467                                                                 numbers_p++);                                                  (head, numbers_p++);
1468                                          break;                                          break;
1469                                  default:                                  default:
1470                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1133  static bool ccs_print_condition(struct c Line 1474  static bool ccs_print_condition(struct c
1474                                  ccs_set_string(head, match ? "=" : "!=");                                  ccs_set_string(head, match ? "=" : "!=");
1475                                  switch (right) {                                  switch (right) {
1476                                  case CCS_NAME_UNION:                                  case CCS_NAME_UNION:
1477                                          ccs_print_name_union(head, names_p++);                                          ccs_print_name_union_quoted
1478                                                    (head, names_p++);
1479                                          break;                                          break;
1480                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1481                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1482                                                                 numbers_p++);                                                  (head, numbers_p++);
1483                                          break;                                          break;
1484                                  default:                                  default:
1485                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1154  static bool ccs_print_condition(struct c Line 1496  static bool ccs_print_condition(struct c
1496                  head->r.cond_step++;                  head->r.cond_step++;
1497                  /* fall through */                  /* fall through */
1498          case 3:          case 3:
1499                  if (cond->grant_log)                  if (cond->grant_log != CCS_GRANTLOG_AUTO)
1500                          ccs_io_printf(head, " grant_log=%s",                          ccs_io_printf(head, " grant_log=%s",
1501                                        ccs_yesno(cond->grant_log == 2));                                        ccs_yesno(cond->grant_log ==
1502                  if (cond->transit) {                                                  CCS_GRANTLOG_YES));
1503                          ccs_set_string(head, " auto_domain_transitition=\"");                  if (cond->transit && !cond->exec_transit) {
1504                          ccs_set_string(head, cond->transit->name);                          const char *name = cond->transit->name;
1505                            ccs_set_string(head, " auto_domain_transition=\"");
1506                            ccs_set_string(head, name);
1507                          ccs_set_string(head, "\"");                          ccs_set_string(head, "\"");
1508                  }                  }
1509                  ccs_set_lf(head);                  ccs_set_lf(head);
# Line 1169  static bool ccs_print_condition(struct c Line 1513  static bool ccs_print_condition(struct c
1513  }  }
1514    
1515  /**  /**
1516   * ccs_fns - Find next set bit.   * ccs_set_group - Print "acl_group " header keyword and category name.
1517   *   *
1518   * @perm: 8 bits value.   * @head:     Pointer to "struct ccs_io_buffer".
1519   * @bit:  First bit to find.   * @category: Category name.
1520   *   *
1521   * Returns next set bit on success, 8 otherwise.   * Returns nothing.
1522   */   */
1523  static u8 ccs_fns(const u8 perm, u8 bit)  static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
 {  
         for ( ; bit < 8; bit++)  
                 if (perm & (1 << bit))  
                         break;  
         return bit;  
 }  
   
 static void ccs_set_group(struct ccs_io_buffer *head)  
1524  {  {
1525          if (head->type == CCS_EXCEPTIONPOLICY)          if (head->type == CCS_EXCEPTIONPOLICY) {
1526                  ccs_io_printf(head, "acl_group %u ", head->r.group_index);                  ccs_print_namespace(head);
1527                    ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
1528            }
1529            ccs_set_string(head, category);
1530  }  }
1531    
1532  /**  /**
# Line 1202  static bool ccs_print_entry(struct ccs_i Line 1541  static bool ccs_print_entry(struct ccs_i
1541                              const struct ccs_acl_info *acl)                              const struct ccs_acl_info *acl)
1542  {  {
1543          const u8 acl_type = acl->type;          const u8 acl_type = acl->type;
1544            const bool may_trigger_transition = acl->cond && acl->cond->transit;
1545            bool first = true;
1546          u8 bit;          u8 bit;
1547          if (head->r.print_cond_part)          if (head->r.print_cond_part)
1548                  goto print_cond_part;                  goto print_cond_part;
1549          if (acl->is_deleted)          if (acl->is_deleted)
1550                  return true;                  return true;
 next:  
         bit = head->r.bit;  
1551          if (!ccs_flush(head))          if (!ccs_flush(head))
1552                  return false;                  return false;
1553          else if (acl_type == CCS_TYPE_PATH_ACL) {          else if (acl_type == CCS_TYPE_PATH_ACL) {
1554                  struct ccs_path_acl *ptr                  struct ccs_path_acl *ptr
1555                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1556                  const u16 perm = ptr->perm;                  const u16 perm = ptr->perm;
1557                  for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {                  for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
1558                          if (!(perm & (1 << bit)))                          if (!(perm & (1 << bit)))
1559                                  continue;                                  continue;
1560                          if (head->r.print_execute_only &&                          if (head->r.print_transition_related_only &&
1561                              bit != CCS_TYPE_EXECUTE                              bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
                             /* && bit != CCS_TYPE_TRANSIT */)  
1562                                  continue;                                  continue;
1563                          break;                          if (first) {
1564                                    ccs_set_group(head, "file ");
1565                                    first = false;
1566                            } else {
1567                                    ccs_set_slash(head);
1568                            }
1569                            ccs_set_string(head, ccs_path_keyword[bit]);
1570                  }                  }
1571                  if (bit >= CCS_MAX_PATH_OPERATION)                  if (first)
1572                          goto done;                          return true;
                 ccs_set_group(head);  
                 ccs_set_string(head, "file ");  
                 ccs_set_string(head, ccs_path_keyword[bit]);  
1573                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1574          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
1575                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1576                  struct ccs_handler_acl *ptr                  struct ccs_handler_acl *ptr
1577                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1578                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1579                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
1580                                 ? "auto_execute_handler " :                                 ? "auto_execute_handler " :
1581                                 "denied_execute_handler ");                                 "denied_execute_handler ");
# Line 1244  next: Line 1584  next:
1584                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
1585                  struct ccs_task_acl *ptr =                  struct ccs_task_acl *ptr =
1586                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1587                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1588                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
1589                                 "auto_domain_transition " :                                 "auto_domain_transition " :
1590                                 "manual_domain_transition ");                                 "manual_domain_transition ");
1591                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1592          } else if (head->r.print_execute_only) {          } else if (head->r.print_transition_related_only &&
1593                       !may_trigger_transition) {
1594                  return true;                  return true;
1595          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1596                  struct ccs_mkdev_acl *ptr =                  struct ccs_mkdev_acl *ptr =
1597                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1598                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1599                  if (bit >= CCS_MAX_MKDEV_OPERATION)                  for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
1600                          goto done;                          if (!(perm & (1 << bit)))
1601                  ccs_set_group(head);                                  continue;
1602                  ccs_set_string(head, "file ");                          if (first) {
1603                  ccs_set_string(head, ccs_mac_keywords[ccs_pnnn2mac[bit]]);                                  ccs_set_group(head, "file ");
1604                                    first = false;
1605                            } else {
1606                                    ccs_set_slash(head);
1607                            }
1608                            ccs_set_string(head, ccs_mac_keywords
1609                                           [ccs_pnnn2mac[bit]]);
1610                    }
1611                    if (first)
1612                            return true;
1613                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1614                  ccs_print_number_union(head, &ptr->mode);                  ccs_print_number_union(head, &ptr->mode);
1615                  ccs_print_number_union(head, &ptr->major);                  ccs_print_number_union(head, &ptr->major);
# Line 1268  next: Line 1617  next:
1617          } else if (acl_type == CCS_TYPE_PATH2_ACL) {          } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1618                  struct ccs_path2_acl *ptr =                  struct ccs_path2_acl *ptr =
1619                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1620                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1621                  if (bit >= CCS_MAX_PATH2_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
1622                          goto done;                          if (!(perm & (1 << bit)))
1623                  ccs_set_group(head);                                  continue;
1624                  ccs_set_string(head, "file ");                          if (first) {
1625                  ccs_set_string(head, ccs_mac_keywords[ccs_pp2mac[bit]]);                                  ccs_set_group(head, "file ");
1626                                    first = false;
1627                            } else {
1628                                    ccs_set_slash(head);
1629                            }
1630                            ccs_set_string(head, ccs_mac_keywords
1631                                           [ccs_pp2mac[bit]]);
1632                    }
1633                    if (first)
1634                            return true;
1635                  ccs_print_name_union(head, &ptr->name1);                  ccs_print_name_union(head, &ptr->name1);
1636                  ccs_print_name_union(head, &ptr->name2);                  ccs_print_name_union(head, &ptr->name2);
1637          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1638                  struct ccs_path_number_acl *ptr =                  struct ccs_path_number_acl *ptr =
1639                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1640                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1641                  if (bit >= CCS_MAX_PATH_NUMBER_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
1642                          goto done;                          if (!(perm & (1 << bit)))
1643                  ccs_set_group(head);                                  continue;
1644                  ccs_set_string(head, "file ");                          if (first) {
1645                  ccs_set_string(head, ccs_mac_keywords[ccs_pn2mac[bit]]);                                  ccs_set_group(head, "file ");
1646                                    first = false;
1647                            } else {
1648                                    ccs_set_slash(head);
1649                            }
1650                            ccs_set_string(head, ccs_mac_keywords
1651                                           [ccs_pn2mac[bit]]);
1652                    }
1653                    if (first)
1654                            return true;
1655                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1656                  ccs_print_number_union(head, &ptr->number);                  ccs_print_number_union(head, &ptr->number);
1657          } else if (acl_type == CCS_TYPE_ENV_ACL) {          } else if (acl_type == CCS_TYPE_ENV_ACL) {
1658                  struct ccs_env_acl *ptr =                  struct ccs_env_acl *ptr =
1659                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1660                  ccs_set_group(head);                  ccs_set_group(head, "misc env ");
                 ccs_set_string(head, "misc env ");  
1661                  ccs_set_string(head, ptr->env->name);                  ccs_set_string(head, ptr->env->name);
1662          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1663                  struct ccs_capability_acl *ptr =                  struct ccs_capability_acl *ptr =
1664                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1665                  ccs_set_group(head);                  ccs_set_group(head, "capability ");
1666                  ccs_set_string(head, "capability ");                  ccs_set_string(head, ccs_mac_keywords
1667                  ccs_set_string(head,                                 [ccs_c2mac[ptr->operation]]);
                                ccs_mac_keywords[ccs_c2mac[ptr->operation]]);  
1668          } else if (acl_type == CCS_TYPE_INET_ACL) {          } else if (acl_type == CCS_TYPE_INET_ACL) {
1669                  struct ccs_inet_acl *ptr =                  struct ccs_inet_acl *ptr =
1670                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1671                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1672                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1673                          goto done;                          if (!(perm & (1 << bit)))
1674                  ccs_set_group(head);                                  continue;
1675                  ccs_set_string(head, "network inet ");                          if (first) {
1676                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network inet ");
1677                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1678                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1679                                    ccs_set_space(head);
1680                                    first = false;
1681                            } else {
1682                                    ccs_set_slash(head);
1683                            }
1684                            ccs_set_string(head, ccs_socket_keyword[bit]);
1685                    }
1686                    if (first)
1687                            return true;
1688                  ccs_set_space(head);                  ccs_set_space(head);
1689                  switch (ptr->address_type) {                  if (ptr->address.group) {
                         char buf[128];  
                 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:  
1690                          ccs_set_string(head, "@");                          ccs_set_string(head, "@");
1691                          ccs_set_string(head,                          ccs_set_string(head,
1692                                         ptr->address.group->group_name->name);                                         ptr->address.group->group_name->name);
1693                          break;                  } else {
1694                  case CCS_IP_ADDRESS_TYPE_IPv4:                          char buf[128];
1695                          ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,                          ccs_print_ip(buf, sizeof(buf), &ptr->address);
                                        ptr->address.ipv4.max);  
                         ccs_io_printf(head, "%s", buf);  
                         break;  
                 case CCS_IP_ADDRESS_TYPE_IPv6:  
                         ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,  
                                        ptr->address.ipv6.max);  
1696                          ccs_io_printf(head, "%s", buf);                          ccs_io_printf(head, "%s", buf);
                         break;  
1697                  }                  }
1698                  ccs_print_number_union(head, &ptr->port);                  ccs_print_number_union(head, &ptr->port);
1699          } else if (acl_type == CCS_TYPE_UNIX_ACL) {          } else if (acl_type == CCS_TYPE_UNIX_ACL) {
1700                  struct ccs_unix_acl *ptr =                  struct ccs_unix_acl *ptr =
1701                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1702                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1703                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1704                          goto done;                          if (!(perm & (1 << bit)))
1705                  ccs_set_group(head);                                  continue;
1706                  ccs_set_string(head, "network unix ");                          if (first) {
1707                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network unix ");
1708                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1709                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1710                                    ccs_set_space(head);
1711                                    first = false;
1712                            } else {
1713                                    ccs_set_slash(head);
1714                            }
1715                            ccs_set_string(head, ccs_socket_keyword[bit]);
1716                    }
1717                    if (first)
1718                            return true;
1719                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1720          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1721                  struct ccs_signal_acl *ptr =                  struct ccs_signal_acl *ptr =
1722                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1723                  ccs_set_group(head);                  ccs_set_group(head, "ipc signal ");
1724                  ccs_set_string(head, "ipc signal ");                  ccs_print_number_union_nospace(head, &ptr->sig);
1725                  ccs_io_printf(head, "%u ", ptr->sig);                  ccs_set_space(head);
1726                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1727          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1728                  struct ccs_mount_acl *ptr =                  struct ccs_mount_acl *ptr =
1729                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1730                  ccs_set_group(head);                  ccs_set_group(head, "file mount");
                 ccs_io_printf(head, "file mount");  
1731                  ccs_print_name_union(head, &ptr->dev_name);                  ccs_print_name_union(head, &ptr->dev_name);
1732                  ccs_print_name_union(head, &ptr->dir_name);                  ccs_print_name_union(head, &ptr->dir_name);
1733                  ccs_print_name_union(head, &ptr->fs_type);                  ccs_print_name_union(head, &ptr->fs_type);
1734                  ccs_print_number_union(head, &ptr->flags);                  ccs_print_number_union(head, &ptr->flags);
1735          }          }
         head->r.bit = bit + 1;  
1736          if (acl->cond) {          if (acl->cond) {
1737                  head->r.print_cond_part = true;                  head->r.print_cond_part = true;
1738                  head->r.cond_step = 0;                  head->r.cond_step = 0;
# Line 1373  print_cond_part: Line 1745  print_cond_part:
1745          } else {          } else {
1746                  ccs_set_lf(head);                  ccs_set_lf(head);
1747          }          }
         switch (acl_type) {  
         case CCS_TYPE_PATH_ACL:  
         case CCS_TYPE_MKDEV_ACL:  
         case CCS_TYPE_PATH2_ACL:  
         case CCS_TYPE_PATH_NUMBER_ACL:  
         case CCS_TYPE_INET_ACL:  
         case CCS_TYPE_UNIX_ACL:  
                 goto next;  
         }  
 done:  
         head->r.bit = 0;  
1748          return true;          return true;
1749  }  }
1750    
1751  /**  /**
1752   * ccs_read_domain2 - Read domain policy.   * ccs_read_domain2 - Read domain policy.
1753   *   *
1754   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1755   * @domain: Pointer to "struct ccs_domain_info".   * @list: Pointer to "struct list_head".
  * @index:  Index number.  
  *  
  * Caller holds ccs_read_lock().  
1756   *   *
1757   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1758     *
1759     * Caller holds ccs_read_lock().
1760   */   */
1761  static bool ccs_read_domain2(struct ccs_io_buffer *head,  static bool ccs_read_domain2(struct ccs_io_buffer *head,
1762                               struct ccs_domain_info *domain,                               struct list_head *list)
                              const u8 index)  
1763  {  {
1764          list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) {          list_for_each_cookie(head->r.acl, list) {
1765                  struct ccs_acl_info *ptr =                  struct ccs_acl_info *ptr =
1766                          list_entry(head->r.acl, typeof(*ptr), list);                          list_entry(head->r.acl, typeof(*ptr), list);
1767                  if (!ccs_print_entry(head, ptr))                  if (!ccs_print_entry(head, ptr))
# Line 1417  static bool ccs_read_domain2(struct ccs_ Line 1776  static bool ccs_read_domain2(struct ccs_
1776   *   *
1777   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1778   *   *
1779     * Returns nothing.
1780     *
1781   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1782   */   */
1783  static void ccs_read_domain(struct ccs_io_buffer *head)  static void ccs_read_domain(struct ccs_io_buffer *head)
# Line 1445  static void ccs_read_domain(struct ccs_i Line 1806  static void ccs_read_domain(struct ccs_i
1806                          ccs_set_lf(head);                          ccs_set_lf(head);
1807                          /* fall through */                          /* fall through */
1808                  case 1:                  case 1:
1809                          if (!ccs_read_domain2(head, domain, 0))                          if (!ccs_read_domain2(head, &domain->acl_info_list))
                                 return;  
                         head->r.step++;  
                         /* fall through */  
                 case 2:  
                         if (!ccs_read_domain2(head, domain, 1))  
1810                                  return;                                  return;
1811                          head->r.step++;                          head->r.step++;
1812                          if (!ccs_set_lf(head))                          if (!ccs_set_lf(head))
1813                                  return;                                  return;
1814                          /* fall through */                          /* fall through */
1815                  case 3:                  case 2:
1816                          head->r.step = 0;                          head->r.step = 0;
1817                          if (head->r.print_this_domain_only)                          if (head->r.print_this_domain_only)
1818                                  goto done;                                  goto done;
# Line 1467  done: Line 1823  done:
1823  }  }
1824    
1825  /**  /**
1826   * ccs_write_domain_profile - Assign profile for specified domain.   * ccs_write_pid - Specify PID to obtain domainname.
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns 0 on success, -EINVAL otherwise.  
  *  
  * This is equivalent to doing  
  *  
  *     ( echo "select " $domainname; echo "use_profile " $profile ) |  
  *     /usr/sbin/ccs-loadpolicy -d  
  *  
  * Caller holds ccs_read_lock().  
  */  
 static int ccs_write_domain_profile(struct ccs_io_buffer *head)  
 {  
         char *data = head->write_buf;  
         char *cp = strchr(data, ' ');  
         struct ccs_domain_info *domain;  
         unsigned int profile;  
         if (!cp)  
                 return -EINVAL;  
         *cp = '\0';  
         profile = simple_strtoul(data, NULL, 10);  
         if (profile >= CCS_MAX_PROFILES)  
                 return -EINVAL;  
         domain = ccs_find_domain(cp + 1);  
         if (domain && (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile]))  
                 domain->profile = (u8) profile;  
         return 0;  
 }  
   
 /**  
  * ccs_read_domain_profile - Read only domainname and profile.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * This is equivalent to doing  
  *  
  *     grep -A 1 '^<kernel>' /proc/ccs/domain_policy |  
  *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )  
  *     domainname = $0; } else if ( $1 == "use_profile" ) {  
  *     print $2 " " domainname; domainname = ""; } } ; '  
  *  
  * Caller holds ccs_read_lock().  
  */  
 static void ccs_read_domain_profile(struct ccs_io_buffer *head)  
 {  
         if (head->r.eof)  
                 return;  
         list_for_each_cookie(head->r.domain, &ccs_domain_list) {  
                 struct ccs_domain_info *domain =  
                         list_entry(head->r.domain, typeof(*domain), list);  
                 if (domain->is_deleted)  
                         continue;  
                 if (!ccs_flush(head))  
                         return;  
                 ccs_io_printf(head, "%u ", domain->profile);  
                 ccs_set_string(head, domain->domainname->name);  
                 ccs_set_lf(head);  
         }  
         head->r.eof = true;  
 }  
   
 /**  
  * ccs_write_pid: Specify PID to obtain domainname.  
1827   *   *
1828   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1829   *   *
# Line 1604  static void ccs_read_pid(struct ccs_io_b Line 1896  static void ccs_read_pid(struct ccs_io_b
1896          }          }
1897  }  }
1898    
1899    /* String table for domain transition control keywords. */
1900  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1901            [CCS_TRANSITION_CONTROL_NO_RESET]      = "no_reset_domain ",
1902            [CCS_TRANSITION_CONTROL_RESET]         = "reset_domain ",
1903          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1904          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1905          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",
1906          [CCS_TRANSITION_CONTROL_KEEP]          = "keep_domain ",          [CCS_TRANSITION_CONTROL_KEEP]          = "keep_domain ",
1907  };  };
1908    
1909    /* String table for grouping keywords. */
1910  static const char * const ccs_group_name[CCS_MAX_GROUP] = {  static const char * const ccs_group_name[CCS_MAX_GROUP] = {
1911          [CCS_PATH_GROUP]    = "path_group ",          [CCS_PATH_GROUP]    = "path_group ",
1912          [CCS_NUMBER_GROUP]  = "number_group ",          [CCS_NUMBER_GROUP]  = "number_group ",
# Line 1626  static const char * const ccs_group_name Line 1922  static const char * const ccs_group_name
1922   */   */
1923  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1924  {  {
1925          char *data = head->write_buf;          const bool is_delete = head->w.is_delete;
1926          const bool is_delete = ccs_str_starts(&data, "delete ");          struct ccs_acl_param param = {
1927          u8 i;                  .ns = head->w.ns,
1928          static const struct {                  .is_delete = is_delete,
1929                  const char *keyword;                  .data = head->write_buf,
                 int (*write) (char *, const bool);  
         } ccs_callback[2] = {  
                 { "aggregator ",    ccs_write_aggregator },  
                 { "deny_autobind ", ccs_write_reserved_port },  
1930          };          };
1931          for (i = 0; i < 2; i++)          u8 i;
1932                  if (ccs_str_starts(&data, ccs_callback[i].keyword))          if (ccs_str_starts(&param.data, "aggregator "))
1933                          return ccs_callback[i].write(data, is_delete);                  return ccs_write_aggregator(&param);
1934            if (ccs_str_starts(&param.data, "deny_autobind "))
1935                    return ccs_write_reserved_port(&param);
1936          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1937                  if (ccs_str_starts(&data, ccs_transition_type[i]))                  if (ccs_str_starts(&param.data, ccs_transition_type[i]))
1938                          return ccs_write_transition_control(data, is_delete,                          return ccs_write_transition_control(&param, i);
                                                             i);  
1939          for (i = 0; i < CCS_MAX_GROUP; i++)          for (i = 0; i < CCS_MAX_GROUP; i++)
1940                  if (ccs_str_starts(&data, ccs_group_name[i]))                  if (ccs_str_starts(&param.data, ccs_group_name[i]))
1941                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(&param, i);
1942          if (ccs_str_starts(&data, "acl_group ")) {          if (ccs_str_starts(&param.data, "acl_group ")) {
1943                  unsigned int group;                  unsigned int group;
1944                  if (sscanf(data, "%u", &group) == 1 &&                  char *data;
1945                      group < CCS_MAX_ACL_GROUPS) {                  group = simple_strtoul(param.data, &data, 10);
1946                          data = strchr(data, ' ');                  if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
1947                          if (data)                          return ccs_write_domain2(head->w.ns,
1948                                  return ccs_write_domain2(data + 1,                                                   &head->w.ns->acl_group[group],
1949                                                           &ccs_acl_group[group],                                                   data, is_delete);
                                                          is_delete);  
                 }  
1950          }          }
1951          return -EINVAL;          return -EINVAL;
1952  }  }
# Line 1672  static int ccs_write_exception(struct cc Line 1963  static int ccs_write_exception(struct cc
1963   */   */
1964  static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)  static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
1965  {  {
1966          list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
1967                                                           namespace_list);
1968            struct list_head *list = &ns->group_list[idx];
1969            list_for_each_cookie(head->r.group, list) {
1970                  struct ccs_group *group =                  struct ccs_group *group =
1971                          list_entry(head->r.group, typeof(*group), head.list);                          list_entry(head->r.group, typeof(*group), head.list);
1972                  list_for_each_cookie(head->r.acl, &group->member_list) {                  list_for_each_cookie(head->r.acl, &group->member_list) {
# Line 1682  static bool ccs_read_group(struct ccs_io Line 1976  static bool ccs_read_group(struct ccs_io
1976                                  continue;                                  continue;
1977                          if (!ccs_flush(head))                          if (!ccs_flush(head))
1978                                  return false;                                  return false;
1979                            ccs_print_namespace(head);
1980                          ccs_set_string(head, ccs_group_name[idx]);                          ccs_set_string(head, ccs_group_name[idx]);
1981                          ccs_set_string(head, group->group_name->name);                          ccs_set_string(head, group->group_name->name);
1982                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
# Line 1698  static bool ccs_read_group(struct ccs_io Line 1993  static bool ccs_read_group(struct ccs_io
1993                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
1994                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
1995                                                       head);                                                       head);
1996                                  if (member->is_ipv6)                                  ccs_print_ip(buffer, sizeof(buffer),
1997                                          ccs_print_ipv6(buffer, sizeof(buffer),                                               &member->address);
                                                        member->min.ipv6,  
                                                        member->max.ipv6);  
                                 else  
                                         ccs_print_ipv4(buffer, sizeof(buffer),  
                                                        member->min.ipv4,  
                                                        member->max.ipv4);  
1998                                  ccs_io_printf(head, " %s", buffer);                                  ccs_io_printf(head, " %s", buffer);
1999                          }                          }
2000                          ccs_set_lf(head);                          ccs_set_lf(head);
# Line 1728  static bool ccs_read_group(struct ccs_io Line 2017  static bool ccs_read_group(struct ccs_io
2017   */   */
2018  static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)  static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
2019  {  {
2020          list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2021                                                           namespace_list);
2022            struct list_head *list = &ns->policy_list[idx];
2023            list_for_each_cookie(head->r.acl, list) {
2024                  struct ccs_acl_head *acl =                  struct ccs_acl_head *acl =
2025                          container_of(head->r.acl, typeof(*acl), list);                          container_of(head->r.acl, typeof(*acl), list);
2026                  if (acl->is_deleted)                  if (acl->is_deleted)
2027                          continue;                          continue;
2028                    if (head->r.print_transition_related_only &&
2029                        idx != CCS_ID_TRANSITION_CONTROL)
2030                            continue;
2031                  if (!ccs_flush(head))                  if (!ccs_flush(head))
2032                          return false;                          return false;
2033                  switch (idx) {                  switch (idx) {
# Line 1740  static bool ccs_read_policy(struct ccs_i Line 2035  static bool ccs_read_policy(struct ccs_i
2035                          {                          {
2036                                  struct ccs_transition_control *ptr =                                  struct ccs_transition_control *ptr =
2037                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2038                                    ccs_print_namespace(head);
2039                                  ccs_set_string(head,                                  ccs_set_string(head,
2040                                                 ccs_transition_type[ptr->type]);                                                 ccs_transition_type[ptr->type]);
2041                                  ccs_set_string(head, ptr->program ?                                  ccs_set_string(head, ptr->program ?
# Line 1753  static bool ccs_read_policy(struct ccs_i Line 2049  static bool ccs_read_policy(struct ccs_i
2049                          {                          {
2050                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
2051                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2052                                    ccs_print_namespace(head);
2053                                  ccs_set_string(head, "aggregator ");                                  ccs_set_string(head, "aggregator ");
2054                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
2055                                  ccs_set_space(head);                                  ccs_set_space(head);
# Line 1764  static bool ccs_read_policy(struct ccs_i Line 2061  static bool ccs_read_policy(struct ccs_i
2061                          {                          {
2062                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
2063                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2064                                  const u16 min_port = ptr->min_port;                                  ccs_print_namespace(head);
                                 const u16 max_port = ptr->max_port;  
2065                                  ccs_set_string(head, "deny_autobind ");                                  ccs_set_string(head, "deny_autobind ");
2066                                  ccs_io_printf(head, "%u", min_port);                                  ccs_print_number_union_nospace(head,
2067                                  if (min_port != max_port)                                                                 &ptr->port);
                                         ccs_io_printf(head, "-%u", max_port);  
2068                          }                          }
2069                          break;                          break;
2070                  default:                  default:
# Line 1786  static bool ccs_read_policy(struct ccs_i Line 2081  static bool ccs_read_policy(struct ccs_i
2081   *   *
2082   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2083   *   *
2084     * Returns nothing.
2085     *
2086   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
2087   */   */
2088  static void ccs_read_exception(struct ccs_io_buffer *head)  static void ccs_read_exception(struct ccs_io_buffer *head)
2089  {  {
2090            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2091                                                           namespace_list);
2092          if (head->r.eof)          if (head->r.eof)
2093                  return;                  return;
2094          while (head->r.step < CCS_MAX_POLICY &&          while (head->r.step < CCS_MAX_POLICY &&
# Line 1803  static void ccs_read_exception(struct cc Line 2102  static void ccs_read_exception(struct cc
2102          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
2103                  return;                  return;
2104          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
2105                 + CCS_MAX_ACL_GROUPS * 2) {                 + CCS_MAX_ACL_GROUPS) {
2106                  head->r.group_index = (head->r.step - CCS_MAX_POLICY                  head->r.acl_group_index =
2107                                         - CCS_MAX_GROUP) / 2;                          head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
2108                  if (!ccs_read_domain2(head,                  if (!ccs_read_domain2(head, &ns->acl_group
2109                                        &ccs_acl_group[head->r.group_index],                                        [head->r.acl_group_index]))
                                       head->r.step & 1))  
2110                          return;                          return;
2111                  head->r.step++;                  head->r.step++;
2112          }          }
2113          head->r.eof = true;          head->r.eof = true;
2114  }  }
2115    
2116  /* Wait queue for ccs_query_list. */  /* Wait queue for kernel -> userspace notification. */
2117  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
2118    /* Wait queue for userspace -> kernel notification. */
2119  static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
2120    
 /* Lock for manipulating ccs_query_list. */  
 static DEFINE_SPINLOCK(ccs_query_list_lock);  
   
2121  /* Structure for query. */  /* Structure for query. */
2122  struct ccs_query {  struct ccs_query {
2123          struct list_head list;          struct list_head list;
2124          char *query;          char *query;
2125          int query_len;          size_t query_len;
2126          unsigned int serial;          unsigned int serial;
2127          int timer;          u8 timer;
2128          int answer;          u8 answer;
2129          u8 retry;          u8 retry;
2130  };  };
2131    
2132  /* The list for "struct ccs_query". */  /* The list for "struct ccs_query". */
2133  static LIST_HEAD(ccs_query_list);  static LIST_HEAD(ccs_query_list);
2134    
2135    /* Lock for manipulating ccs_query_list. */
2136    static DEFINE_SPINLOCK(ccs_query_list_lock);
2137    
2138  /* Number of "struct file" referring /proc/ccs/query interface. */  /* Number of "struct file" referring /proc/ccs/query interface. */
2139  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
2140    
2141    /**
2142     * ccs_truncate - Truncate a line.
2143     *
2144     * @str: String to truncate.
2145     *
2146     * Returns length of truncated @str.
2147     */
2148  static int ccs_truncate(char *str)  static int ccs_truncate(char *str)
2149  {  {
2150          char *start = str;          char *start = str;
# Line 1848  static int ccs_truncate(char *str) Line 2154  static int ccs_truncate(char *str)
2154          return strlen(start) + 1;          return strlen(start) + 1;
2155  }  }
2156    
2157    /**
2158     * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
2159     *
2160     * @header: Lines containing ACL.
2161     *
2162     * Returns nothing.
2163     */
2164  static void ccs_add_entry(char *header)  static void ccs_add_entry(char *header)
2165  {  {
2166          char *buffer;          char *buffer;
# Line 1896  static void ccs_add_entry(char *header) Line 2209  static void ccs_add_entry(char *header)
2209          if (symlink)          if (symlink)
2210                  ccs_addprintf(buffer, len, "%s", symlink);                  ccs_addprintf(buffer, len, "%s", symlink);
2211          ccs_normalize_line(buffer);          ccs_normalize_line(buffer);
2212          if (!ccs_write_domain2(buffer, ccs_current_domain(), false))          {
2213                  ccs_update_stat(CCS_STAT_POLICY_UPDATES);                  struct ccs_domain_info *domain = ccs_current_domain();
2214                    if (!ccs_write_domain2(domain->ns, &domain->acl_info_list,
2215                                           buffer, false))
2216                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2217            }
2218          kfree(buffer);          kfree(buffer);
2219  }  }
2220    
# Line 1923  int ccs_supervisor(struct ccs_request_in Line 2240  int ccs_supervisor(struct ccs_request_in
2240          va_start(args, fmt);          va_start(args, fmt);
2241          len = vsnprintf((char *) &len, 1, fmt, args) + 1;          len = vsnprintf((char *) &len, 1, fmt, args) + 1;
2242          va_end(args);          va_end(args);
2243          /* Write /proc/ccs/grant_log or /proc/ccs/reject_log . */          /* Write /proc/ccs/audit. */
2244          va_start(args, fmt);          va_start(args, fmt);
2245          ccs_write_log2(r, len, fmt, args);          ccs_write_log2(r, len, fmt, args);
2246          va_end(args);          va_end(args);
# Line 1939  int ccs_supervisor(struct ccs_request_in Line 2256  int ccs_supervisor(struct ccs_request_in
2256                  error = -EPERM;                  error = -EPERM;
2257                  if (atomic_read(&ccs_query_observers))                  if (atomic_read(&ccs_query_observers))
2258                          break;                          break;
2259                  if (ccs_current_flags() & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  if (r->dont_sleep_on_enforce_error)
2260                          goto out;                          goto out;
2261                  p = ccs_profile(r->profile);                  p = ccs_profile(r->profile);
2262                  /* Check enforcing_penalty parameter. */                  /* Check enforcing_penalty parameter. */
# Line 1950  int ccs_supervisor(struct ccs_request_in Line 2267  int ccs_supervisor(struct ccs_request_in
2267                  goto out;                  goto out;
2268          case CCS_CONFIG_LEARNING:          case CCS_CONFIG_LEARNING:
2269                  error = 0;                  error = 0;
2270                  /* Check mac_learning_entry parameter. */                  /* Check max_learning_entry parameter. */
2271                  if (ccs_domain_quota_ok(r))                  if (ccs_domain_quota_ok(r))
2272                          break;                          break;
2273                  /* fall through */                  /* fall through */
# Line 2054  static int ccs_poll_query(struct file *f Line 2371  static int ccs_poll_query(struct file *f
2371   * ccs_read_query - Read access requests which violated policy in enforcing mode.   * ccs_read_query - Read access requests which violated policy in enforcing mode.
2372   *   *
2373   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2374     *
2375     * Returns nothing.
2376   */   */
2377  static void ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2378  {  {
2379          struct list_head *tmp;          struct list_head *tmp;
2380          int pos = 0;          unsigned int pos = 0;
2381          int len = 0;          size_t len = 0;
2382          char *buf;          char *buf;
2383          if (head->r.w_pos)          if (head->r.w_pos)
2384                  return;                  return;
2385          if (head->read_buf) {          kfree(head->read_buf);
2386                  kfree(head->read_buf);          head->read_buf = NULL;
                 head->read_buf = NULL;  
         }  
2387          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2388          list_for_each(tmp, &ccs_query_list) {          list_for_each(tmp, &ccs_query_list) {
2389                  struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);                  struct ccs_query *ptr = list_entry(tmp, typeof(*ptr), list);
# Line 2098  static void ccs_read_query(struct ccs_io Line 2415  static void ccs_read_query(struct ccs_io
2415                   * can change, but I don't care.                   * can change, but I don't care.
2416                   */                   */
2417                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2418                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,                          snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
2419                                   ptr->retry, ptr->query);                                   ptr->retry, ptr->query);
2420                  break;                  break;
2421          }          }
# Line 2139  static int ccs_write_answer(struct ccs_i Line 2456  static int ccs_write_answer(struct ccs_i
2456                  if (ptr->serial != serial)                  if (ptr->serial != serial)
2457                          continue;                          continue;
2458                  if (!ptr->answer)                  if (!ptr->answer)
2459                          ptr->answer = answer;                          ptr->answer = (u8) answer;
2460                  break;                  break;
2461          }          }
2462          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2148  static int ccs_write_answer(struct ccs_i Line 2465  static int ccs_write_answer(struct ccs_i
2465  }  }
2466    
2467  /**  /**
2468   * ccs_read_version: Get version.   * ccs_read_version - Get version.
2469   *   *
2470   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2471     *
2472     * Returns nothing.
2473   */   */
2474  static void ccs_read_version(struct ccs_io_buffer *head)  static void ccs_read_version(struct ccs_io_buffer *head)
2475  {  {
2476          if (head->r.eof)          if (head->r.eof)
2477                  return;                  return;
2478          ccs_set_string(head, "1.8.0-pre");          ccs_set_string(head, "1.8.3");
2479          head->r.eof = true;          head->r.eof = true;
2480  }  }
2481    
2482    /* String table for /proc/ccs/stat interface. */
2483    static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
2484            [CCS_STAT_POLICY_UPDATES]    = "update:",
2485            [CCS_STAT_POLICY_LEARNING]   = "violation in learning mode:",
2486            [CCS_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:",
2487            [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
2488    };
2489    
2490    /* String table for /proc/ccs/stat interface. */
2491    static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2492            [CCS_MEMORY_POLICY]     = "policy:",
2493            [CCS_MEMORY_AUDIT]      = "audit log:",
2494            [CCS_MEMORY_QUERY]      = "query message:",
2495    };
2496    
2497    /* Timestamp counter for last updated. */
2498    static unsigned int ccs_stat_updated[CCS_MAX_POLICY_STAT];
2499    /* Counter for number of updates. */
2500    static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
2501    
2502    /**
2503     * ccs_update_stat - Update statistic counters.
2504     *
2505     * @index: Index for policy type.
2506     *
2507     * Returns nothing.
2508     */
2509    void ccs_update_stat(const u8 index)
2510    {
2511            struct timeval tv;
2512            do_gettimeofday(&tv);
2513            /*
2514             * I don't use atomic operations because race condition is not fatal.
2515             */
2516            ccs_stat_updated[index]++;
2517            ccs_stat_modified[index] = tv.tv_sec;
2518    }
2519    
2520    /**
2521     * ccs_read_stat - Read statistic data.
2522     *
2523     * @head: Pointer to "struct ccs_io_buffer".
2524     *
2525     * Returns nothing.
2526     */
2527    static void ccs_read_stat(struct ccs_io_buffer *head)
2528    {
2529            u8 i;
2530            unsigned int total = 0;
2531            if (head->r.eof)
2532                    return;
2533            for (i = 0; i < CCS_MAX_POLICY_STAT; i++) {
2534                    ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i],
2535                                  ccs_stat_updated[i]);
2536                    if (ccs_stat_modified[i]) {
2537                            struct ccs_time stamp;
2538                            ccs_convert_time(ccs_stat_modified[i], &stamp);
2539                            ccs_io_printf(head, " (Last: %04u/%02u/%02u "
2540                                          "%02u:%02u:%02u)",
2541                                          stamp.year, stamp.month, stamp.day,
2542                                          stamp.hour, stamp.min, stamp.sec);
2543                    }
2544                    ccs_set_lf(head);
2545            }
2546            for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
2547                    unsigned int used = ccs_memory_used[i];
2548                    total += used;
2549                    ccs_io_printf(head, "Memory used by %-22s %10u",
2550                                  ccs_memory_headers[i], used);
2551                    used = ccs_memory_quota[i];
2552                    if (used)
2553                            ccs_io_printf(head, " (Quota: %10u)", used);
2554                    ccs_set_lf(head);
2555            }
2556            ccs_io_printf(head, "Total memory used:                    %10u\n",
2557                          total);
2558            head->r.eof = true;
2559    }
2560    
2561    /**
2562     * ccs_write_stat - Set memory quota.
2563     *
2564     * @head: Pointer to "struct ccs_io_buffer".
2565     *
2566     * Returns 0.
2567     */
2568    static int ccs_write_stat(struct ccs_io_buffer *head)
2569    {
2570            char *data = head->write_buf;
2571            u8 i;
2572            if (ccs_str_starts(&data, "Memory used by "))
2573                    for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2574                            if (ccs_str_starts(&data, ccs_memory_headers[i])) {
2575                                    if (*data == ' ')
2576                                            data++;
2577                                    ccs_memory_quota[i] =
2578                                            simple_strtoul(data, NULL, 10);
2579                            }
2580            return 0;
2581    }
2582    
2583  /**  /**
2584   * ccs_open_control - open() for /proc/ccs/ interface.   * ccs_open_control - open() for /proc/ccs/ interface.
2585   *   *
2586   * @type: Type of interface.   * @type: Type of interface.
2587   * @file: Pointer to "struct file".   * @file: Pointer to "struct file".
2588   *   *
2589   * Associates policy handler and returns 0 on success, -ENOMEM otherwise.   * Returns 0 on success, negative value otherwise.
2590   */   */
2591  int ccs_open_control(const u8 type, struct file *file)  int ccs_open_control(const u8 type, struct file *file)
2592  {  {
# Line 2175  int ccs_open_control(const u8 type, stru Line 2595  int ccs_open_control(const u8 type, stru
2595                  return -ENOMEM;                  return -ENOMEM;
2596          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2597          head->type = type;          head->type = type;
2598          switch (type) {          if (type == CCS_EXECUTE_HANDLER) {
         case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */  
                 head->write = ccs_write_domain;  
                 head->read = ccs_read_domain;  
                 break;  
         case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */  
                 head->write = ccs_write_exception;  
                 head->read = ccs_read_exception;  
                 break;  
         case CCS_GRANTLOG: /* /proc/ccs/grant_log */  
         case CCS_REJECTLOG: /* /proc/ccs/reject_log */  
                 head->poll = ccs_poll_log;  
                 head->read = ccs_read_log;  
                 break;  
         case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */  
                 head->write = ccs_write_domain_profile;  
                 head->read = ccs_read_domain_profile;  
                 break;  
         case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */  
2599                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
2600                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
2601                          kfree(head);                          kfree(head);
2602                          return -EPERM;                          return -EPERM;
2603                  }                  }
                 /* fall through */  
         case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */  
                 head->write = ccs_write_pid;  
                 head->read = ccs_read_pid;  
                 break;  
         case CCS_VERSION: /* /proc/ccs/version */  
                 head->read = ccs_read_version;  
                 head->readbuf_size = 128;  
                 break;  
         case CCS_MEMINFO: /* /proc/ccs/meminfo */  
                 head->write = ccs_write_memory_quota;  
                 head->read = ccs_read_memory_counter;  
                 head->readbuf_size = 512;  
                 break;  
         case CCS_PROFILE: /* /proc/ccs/profile */  
                 head->write = ccs_write_profile;  
                 head->read = ccs_read_profile;  
                 break;  
         case CCS_QUERY: /* /proc/ccs/query */  
                 head->poll = ccs_poll_query;  
                 head->write = ccs_write_answer;  
                 head->read = ccs_read_query;  
                 break;  
         case CCS_MANAGER: /* /proc/ccs/manager */  
                 head->write = ccs_write_manager;  
                 head->read = ccs_read_manager;  
                 break;  
2604          }          }
2605          if (!(file->f_mode & FMODE_READ)) {          if ((file->f_mode & FMODE_READ) && type != CCS_AUDIT &&
2606                  /*              type != CCS_QUERY) {
                  * No need to allocate read_buf since it is not opened  
                  * for reading.  
                  */  
                 head->read = NULL;  
                 head->poll = NULL;  
         } else if (!head->poll) {  
2607                  /* Don't allocate read_buf for poll() access. */                  /* Don't allocate read_buf for poll() access. */
2608                  if (!head->readbuf_size)                  head->readbuf_size = 4096;
                         head->readbuf_size = 4096;  
2609                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
2610                  if (!head->read_buf) {                  if (!head->read_buf) {
2611                          kfree(head);                          kfree(head);
2612                          return -ENOMEM;                          return -ENOMEM;
2613                  }                  }
2614          }          }
2615          if (!(file->f_mode & FMODE_WRITE)) {          if (file->f_mode & FMODE_WRITE) {
                 /*  
                  * No need to allocate write_buf since it is not opened  
                  * for writing.  
                  */  
                 head->write = NULL;  
         } else if (head->write) {  
2616                  head->writebuf_size = 4096;                  head->writebuf_size = 4096;
2617                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
2618                  if (!head->write_buf) {                  if (!head->write_buf) {
# Line 2260  int ccs_open_control(const u8 type, stru Line 2622  int ccs_open_control(const u8 type, stru
2622                  }                  }
2623          }          }
2624          /*          /*
2625           * If the file is /proc/ccs/query , increment the observer counter.           * If the file is /proc/ccs/query, increment the observer counter.
2626           * The obserber counter is used by ccs_supervisor() to see if           * The obserber counter is used by ccs_supervisor() to see if
2627           * there is some process monitoring /proc/ccs/query.           * there is some process monitoring /proc/ccs/query.
2628           */           */
2629          if (type == CCS_QUERY)          if (type == CCS_QUERY)
2630                  atomic_inc(&ccs_query_observers);                  atomic_inc(&ccs_query_observers);
         else if (type != CCS_GRANTLOG && type != CCS_REJECTLOG)  
                 head->reader_idx = ccs_lock();  
2631          file->private_data = head;          file->private_data = head;
2632            ccs_notify_gc(head, true);
2633          return 0;          return 0;
2634  }  }
2635    
# Line 2278  int ccs_open_control(const u8 type, stru Line 2639  int ccs_open_control(const u8 type, stru
2639   * @file: Pointer to "struct file".   * @file: Pointer to "struct file".
2640   * @wait: Pointer to "poll_table".   * @wait: Pointer to "poll_table".
2641   *   *
2642     * Returns return value of poll().
2643     *
2644   * Waits for read readiness.   * Waits for read readiness.
2645   * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and   * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and
2646   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by   * /proc/ccs/audit is handled by /usr/sbin/ccs-auditd.
  * /usr/sbin/ccs-auditd .  
2647   */   */
2648  int ccs_poll_control(struct file *file, poll_table *wait)  int ccs_poll_control(struct file *file, poll_table *wait)
2649  {  {
2650          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2651          if (!head->poll)          switch (head->type) {
2652            case CCS_AUDIT:
2653                    return ccs_poll_log(file, wait);
2654            case CCS_QUERY:
2655                    return ccs_poll_query(file, wait);
2656            default:
2657                  return -ENOSYS;                  return -ENOSYS;
2658          return head->poll(file, wait);          }
2659    }
2660    
2661    /**
2662     * ccs_set_namespace_cursor - Set namespace to read.
2663     *
2664     * @head: Pointer to "struct ccs_io_buffer".
2665     *
2666     * Returns nothing.
2667     */
2668    static inline void ccs_set_namespace_cursor(struct ccs_io_buffer *head)
2669    {
2670            struct list_head *ns;
2671            if (head->type != CCS_EXCEPTIONPOLICY && head->type != CCS_PROFILE)
2672                    return;
2673            /*
2674             * If this is the first read, or reading previous namespace finished
2675             * and has more namespaces to read, update the namespace cursor.
2676             */
2677            ns = head->r.ns;
2678            if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
2679                    /* Clearing is OK because ccs_flush() returned true. */
2680                    memset(&head->r, 0, sizeof(head->r));
2681                    head->r.ns = ns ? ns->next : ccs_namespace_list.next;
2682            }
2683    }
2684    
2685    /**
2686     * ccs_has_more_namespace - Check for unread namespaces.
2687     *
2688     * @head: Pointer to "struct ccs_io_buffer".
2689     *
2690     * Returns true if we have more entries to print, false otherwise.
2691     */
2692    static inline bool ccs_has_more_namespace(struct ccs_io_buffer *head)
2693    {
2694            return (head->type == CCS_EXCEPTIONPOLICY ||
2695                    head->type == CCS_PROFILE) && head->r.eof &&
2696                    head->r.ns->next != &ccs_namespace_list;
2697  }  }
2698    
2699  /**  /**
2700   * ccs_read_control - read() for /proc/ccs/ interface.   * ccs_read_control - read() for /proc/ccs/ interface.
2701   *   *
2702   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2703   * @buffer:     Poiner to buffer to write to.   * @buffer:     Poiner to buffer to write to.
2704   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2705   *   *
2706   * Returns bytes read on success, negative value otherwise.   * Returns bytes read on success, negative value otherwise.
2707   */   */
2708  int ccs_read_control(struct file *file, char __user *buffer,  ssize_t ccs_read_control(struct ccs_io_buffer *head, char __user *buffer,
2709                       const int buffer_len)                           const size_t buffer_len)
2710  {  {
2711          int len;          int len;
         struct ccs_io_buffer *head = file->private_data;  
2712          int idx;          int idx;
         if (!head->read)  
                 return -ENOSYS;  
2713          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2714                  return -EFAULT;                  return -EFAULT;
2715          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
# Line 2317  int ccs_read_control(struct file *file, Line 2719  int ccs_read_control(struct file *file,
2719          idx = ccs_read_lock();          idx = ccs_read_lock();
2720          if (ccs_flush(head))          if (ccs_flush(head))
2721                  /* Call the policy handler. */                  /* Call the policy handler. */
2722                  head->read(head);                  do {
2723          ccs_flush(head);                          ccs_set_namespace_cursor(head);
2724                            switch (head->type) {
2725                            case CCS_DOMAINPOLICY:
2726                                    ccs_read_domain(head);
2727                                    break;
2728                            case CCS_EXCEPTIONPOLICY:
2729                                    ccs_read_exception(head);
2730                                    break;
2731                            case CCS_AUDIT:
2732                                    ccs_read_log(head);
2733                                    break;
2734                            case CCS_EXECUTE_HANDLER:
2735                            case CCS_PROCESS_STATUS:
2736                                    ccs_read_pid(head);
2737                                    break;
2738                            case CCS_VERSION:
2739                                    ccs_read_version(head);
2740                                    break;
2741                            case CCS_STAT:
2742                                    ccs_read_stat(head);
2743                                    break;
2744                            case CCS_PROFILE:
2745                                    ccs_read_profile(head);
2746                                    break;
2747                            case CCS_QUERY:
2748                                    ccs_read_query(head);
2749                                    break;
2750                            case CCS_MANAGER:
2751                                    ccs_read_manager(head);
2752                                    break;
2753                            }
2754                    } while (ccs_flush(head) && ccs_has_more_namespace(head));
2755          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2756          len = head->read_user_buf - buffer;          len = head->read_user_buf - buffer;
2757          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2326  int ccs_read_control(struct file *file, Line 2759  int ccs_read_control(struct file *file,
2759  }  }
2760    
2761  /**  /**
2762     * ccs_parse_policy - Parse a policy line.
2763     *
2764     * @head: Poiter to "struct ccs_io_buffer".
2765     * @line: Line to parse.
2766     *
2767     * Returns 0 on success, negative value otherwise.
2768     *
2769     * Caller holds ccs_read_lock().
2770     */
2771    static int ccs_parse_policy(struct ccs_io_buffer *head, char *line)
2772    {
2773            /* Delete request? */
2774            head->w.is_delete = !strncmp(line, "delete ", 7);
2775            if (head->w.is_delete)
2776                    memmove(line, line + 7, strlen(line + 7) + 1);
2777            /* Selecting namespace to update. */
2778            if (head->type == CCS_EXCEPTIONPOLICY || head->type == CCS_PROFILE) {
2779                    if (*line == '<') {
2780                            char *cp = strchr(line, ' ');
2781                            if (cp) {
2782                                    *cp++ = '\0';
2783                                    head->w.ns = ccs_assign_namespace(line);
2784                                    memmove(line, cp, strlen(cp) + 1);
2785                            } else
2786                                    head->w.ns = NULL;
2787                    } else
2788                            head->w.ns = &ccs_kernel_namespace;
2789                    /* Don't allow updating if namespace is invalid. */
2790                    if (!head->w.ns)
2791                            return -ENOENT;
2792            }
2793            /* Do the update. */
2794            switch (head->type) {
2795            case CCS_DOMAINPOLICY:
2796                    return ccs_write_domain(head);
2797            case CCS_EXCEPTIONPOLICY:
2798                    return ccs_write_exception(head);
2799            case CCS_EXECUTE_HANDLER:
2800            case CCS_PROCESS_STATUS:
2801                    return ccs_write_pid(head);
2802            case CCS_STAT:
2803                    return ccs_write_stat(head);
2804            case CCS_PROFILE:
2805                    return ccs_write_profile(head);
2806            case CCS_QUERY:
2807                    return ccs_write_answer(head);
2808            case CCS_MANAGER:
2809                    return ccs_write_manager(head);
2810            default:
2811                    return -ENOSYS;
2812            }
2813    }
2814    
2815    /**
2816   * ccs_write_control - write() for /proc/ccs/ interface.   * ccs_write_control - write() for /proc/ccs/ interface.
2817   *   *
2818   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2819   * @buffer:     Pointer to buffer to read from.   * @buffer:     Pointer to buffer to read from.
2820   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2821   *   *
2822   * Returns @buffer_len on success, negative value otherwise.   * Returns @buffer_len on success, negative value otherwise.
2823   */   */
2824  int ccs_write_control(struct file *file, const char __user *buffer,  ssize_t ccs_write_control(struct ccs_io_buffer *head,
2825                        const int buffer_len)                            const char __user *buffer, const size_t buffer_len)
2826  {  {
         struct ccs_io_buffer *head = file->private_data;  
2827          int error = buffer_len;          int error = buffer_len;
2828          int avail_len = buffer_len;          size_t avail_len = buffer_len;
2829          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2830          int idx;          int idx;
         if (!head->write)  
                 return -ENOSYS;  
2831          if (!access_ok(VERIFY_READ, buffer, buffer_len))          if (!access_ok(VERIFY_READ, buffer, buffer_len))
2832                  return -EFAULT;                  return -EFAULT;
2833          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2834                  return -EINTR;                  return -EINTR;
2835          idx = ccs_read_lock();          idx = ccs_read_lock();
         /* Don't allow updating policies by non manager programs. */  
         if (head->write != ccs_write_pid && head->write != ccs_write_domain &&  
             !ccs_manager()) {  
                 ccs_read_unlock(idx);  
                 mutex_unlock(&head->io_sem);  
                 return -EPERM;  
         }  
2836          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2837          while (avail_len > 0) {          while (avail_len > 0) {
2838                  char c;                  char c;
# Line 2384  int ccs_write_control(struct file *file, Line 2861  int ccs_write_control(struct file *file,
2861                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2862                  head->w.avail = 0;                  head->w.avail = 0;
2863                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2864                  if (head->write(head))                  if (!strcmp(cp0, "reset")) {
2865                            head->w.ns = &ccs_kernel_namespace;
2866                            head->w.domain = NULL;
2867                            memset(&head->r, 0, sizeof(head->r));
2868                          continue;                          continue;
2869                    }
2870                    /* Don't allow updating policies by non manager programs. */
2871                  switch (head->type) {                  switch (head->type) {
2872                    case CCS_PROCESS_STATUS:
2873                            /* This does not write anything. */
2874                            break;
2875                  case CCS_DOMAINPOLICY:                  case CCS_DOMAINPOLICY:
2876                            if (ccs_select_domain(head, cp0))
2877                                    continue;
2878                            /* fall through */
2879                  case CCS_EXCEPTIONPOLICY:                  case CCS_EXCEPTIONPOLICY:
2880                  case CCS_DOMAIN_STATUS:                          if (!strcmp(cp0, "select transition_only")) {
2881                  case CCS_MEMINFO:                                  head->r.print_transition_related_only = true;
2882                  case CCS_PROFILE:                                  continue;
2883                  case CCS_MANAGER:                          }
2884                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);                          /* fall through */
2885                    default:
2886                            if (!ccs_manager()) {
2887                                    error = -EPERM;
2888                                    goto out;
2889                            }
2890                    }
2891                    switch (ccs_parse_policy(head, cp0)) {
2892                    case -EPERM:
2893                            error = -EPERM;
2894                            goto out;
2895                    case 0:
2896                            /* Update statistics. */
2897                            switch (head->type) {
2898                            case CCS_DOMAINPOLICY:
2899                            case CCS_EXCEPTIONPOLICY:
2900                            case CCS_STAT:
2901                            case CCS_PROFILE:
2902                            case CCS_MANAGER:
2903                                    ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2904                                    break;
2905                            default:
2906                                    break;
2907                            }
2908                            break;
2909                  }                  }
2910          }          }
2911    out:
2912          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2913          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2914          return error;          return error;
# Line 2404  int ccs_write_control(struct file *file, Line 2917  int ccs_write_control(struct file *file,
2917  /**  /**
2918   * ccs_close_control - close() for /proc/ccs/ interface.   * ccs_close_control - close() for /proc/ccs/ interface.
2919   *   *
2920   * @file: Pointer to "struct file".   * @head: Pointer to "struct ccs_io_buffer".
2921   *   *
2922   * Releases memory and returns 0.   * Returns 0.
2923   */   */
2924  int ccs_close_control(struct file *file)  int ccs_close_control(struct ccs_io_buffer *head)
2925  {  {
         struct ccs_io_buffer *head = file->private_data;  
         const bool is_write = head->write_buf != NULL;  
         const u8 type = head->type;  
2926          /*          /*
2927           * If the file is /proc/ccs/query , decrement the observer counter.           * If the file is /proc/ccs/query, decrement the observer counter.
2928           */           */
2929          if (type == CCS_QUERY) {          if (head->type == CCS_QUERY &&
2930                  if (atomic_dec_and_test(&ccs_query_observers))              atomic_dec_and_test(&ccs_query_observers))
2931                          wake_up_all(&ccs_answer_wait);                  wake_up_all(&ccs_answer_wait);
2932          } else if (type != CCS_GRANTLOG && type != CCS_REJECTLOG)          ccs_notify_gc(head, false);
                 ccs_unlock(head->reader_idx);  
         /* Release memory used for policy I/O. */  
         kfree(head->read_buf);  
         head->read_buf = NULL;  
         kfree(head->write_buf);  
         head->write_buf = NULL;  
         kfree(head);  
         head = NULL;  
         file->private_data = NULL;  
         if (is_write)  
                 ccs_run_gc();  
2933          return 0;          return 0;
2934  }  }
2935    
2936    /**
2937     * ccs_policy_io_init - Register hooks for policy I/O.
2938     *
2939     * Returns nothing.
2940     */
2941  void __init ccs_policy_io_init(void)  void __init ccs_policy_io_init(void)
2942  {  {
2943          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;
2944  }  }
2945    
2946    /**
2947     * ccs_load_builtin_policy - Load built-in policy.
2948     *
2949     * Returns nothing.
2950     */
2951    void __init ccs_load_builtin_policy(void)
2952    {
2953            /*
2954             * This include file is manually created and contains built-in policy
2955             * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
2956             * "ccs_builtin_domain_policy", "ccs_builtin_manager",
2957             * "ccs_builtin_stat" in the form of "static char [] __initdata".
2958             */
2959    #include "builtin-policy.h"
2960            u8 i;
2961            const int idx = ccs_read_lock();
2962            for (i = 0; i < 5; i++) {
2963                    struct ccs_io_buffer head = { };
2964                    char *start = "";
2965                    switch (i) {
2966                    case 0:
2967                            start = ccs_builtin_profile;
2968                            head.type = CCS_PROFILE;
2969                            break;
2970                    case 1:
2971                            start = ccs_builtin_exception_policy;
2972                            head.type = CCS_EXCEPTIONPOLICY;
2973                            break;
2974                    case 2:
2975                            start = ccs_builtin_domain_policy;
2976                            head.type = CCS_DOMAINPOLICY;
2977                            break;
2978                    case 3:
2979                            start = ccs_builtin_manager;
2980                            head.type = CCS_MANAGER;
2981                            break;
2982                    case 4:
2983                            start = ccs_builtin_stat;
2984                            head.type = CCS_STAT;
2985                            break;
2986                    }
2987                    while (1) {
2988                            char *end = strchr(start, '\n');
2989                            if (!end)
2990                                    break;
2991                            *end = '\0';
2992                            ccs_normalize_line(start);
2993                            head.write_buf = start;
2994                            ccs_parse_policy(&head, start);
2995                            start = end + 1;
2996                    }
2997            }
2998            ccs_read_unlock(idx);
2999    #ifdef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
3000            ccs_check_profile();
3001    #endif
3002    }

Legend:
Removed from v.4056  
changed lines
  Added in v.5526

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