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

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 3961 by kumaneko, Tue Sep 7 05:07:31 2010 UTC revision 4080 by kumaneko, Fri Oct 22 03:32:47 2010 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2010  NTT DATA CORPORATION   * Copyright (C) 2005-2010  NTT DATA CORPORATION
5   *   *
6   * Version: 1.8.0-pre   2010/09/01   * Version: 1.8.0-pre   2010/10/22
7   *   *
8   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
9   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 12  Line 12 
12    
13  #include "internal.h"  #include "internal.h"
14    
 struct ccs_preference ccs_preference = {  
 #ifdef CONFIG_CCSECURITY_AUDIT  
         .audit_max_grant_log = CONFIG_CCSECURITY_MAX_GRANT_LOG,  
         .audit_max_reject_log = CONFIG_CCSECURITY_MAX_REJECT_LOG,  
 #endif  
         .audit_task_info = true,  
         .audit_path_info = true,  
         .enforcing_penalty = 0,  
         .enforcing_verbose = true,  
         .learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY,  
         .learning_verbose = false,  
         .learning_exec_realpath = true,  
         .learning_exec_argv0 = true,  
         .learning_symlink_target = true,  
         .permissive_verbose = true,  
 };  
   
15  /* Profile version. Currently only 20100903 is defined. */  /* Profile version. Currently only 20100903 is defined. */
16  static unsigned int ccs_profile_version;  static unsigned int ccs_profile_version;
17    
18  /* Profile table. Memory is allocated as needed. */  /* Profile table. Memory is allocated as needed. */
19  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
20    
21  /* String table for functionality that takes 4 modes. */  /* String table for operation mode. */
22  const char *ccs_mode[CCS_CONFIG_MAX_MODE] = {  const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
23          [CCS_CONFIG_DISABLED] = "disabled",          [CCS_CONFIG_DISABLED]   = "disabled",
24          [CCS_CONFIG_LEARNING] = "learning",          [CCS_CONFIG_LEARNING]   = "learning",
25          [CCS_CONFIG_PERMISSIVE] = "permissive",          [CCS_CONFIG_PERMISSIVE] = "permissive",
26          [CCS_CONFIG_ENFORCING] = "enforcing"          [CCS_CONFIG_ENFORCING]  = "enforcing"
27    };
28    
29    /* String table for /proc/ccs/profile interface. */
30    const char * const ccs_mac_keywords[CCS_MAX_MAC_INDEX
31                                        + CCS_MAX_MAC_CATEGORY_INDEX] = {
32            /* CONFIG::file group */
33            [CCS_MAC_FILE_EXECUTE]    = "execute",
34            [CCS_MAC_FILE_OPEN]       = "open",
35            [CCS_MAC_FILE_CREATE]     = "create",
36            [CCS_MAC_FILE_UNLINK]     = "unlink",
37            [CCS_MAC_FILE_GETATTR]    = "getattr",
38            [CCS_MAC_FILE_MKDIR]      = "mkdir",
39            [CCS_MAC_FILE_RMDIR]      = "rmdir",
40            [CCS_MAC_FILE_MKFIFO]     = "mkfifo",
41            [CCS_MAC_FILE_MKSOCK]     = "mksock",
42            [CCS_MAC_FILE_TRUNCATE]   = "truncate",
43            [CCS_MAC_FILE_SYMLINK]    = "symlink",
44            [CCS_MAC_FILE_MKBLOCK]    = "mkblock",
45            [CCS_MAC_FILE_MKCHAR]     = "mkchar",
46            [CCS_MAC_FILE_LINK]       = "link",
47            [CCS_MAC_FILE_RENAME]     = "rename",
48            [CCS_MAC_FILE_CHMOD]      = "chmod",
49            [CCS_MAC_FILE_CHOWN]      = "chown",
50            [CCS_MAC_FILE_CHGRP]      = "chgrp",
51            [CCS_MAC_FILE_IOCTL]      = "ioctl",
52            [CCS_MAC_FILE_CHROOT]     = "chroot",
53            [CCS_MAC_FILE_MOUNT]      = "mount",
54            [CCS_MAC_FILE_UMOUNT]     = "unmount",
55            [CCS_MAC_FILE_PIVOT_ROOT] = "pivot_root",
56            /* CONFIG::misc group */
57            [CCS_MAC_ENVIRON] = "env",
58            /* CONFIG::network group */
59            [CCS_MAC_NETWORK_INET_STREAM_BIND]       = "inet_stream_bind",
60            [CCS_MAC_NETWORK_INET_STREAM_LISTEN]     = "inet_stream_listen",
61            [CCS_MAC_NETWORK_INET_STREAM_CONNECT]    = "inet_stream_connect",
62            [CCS_MAC_NETWORK_INET_STREAM_ACCEPT]     = "inet_stream_accept",
63            [CCS_MAC_NETWORK_INET_DGRAM_BIND]        = "inet_dgram_bind",
64            [CCS_MAC_NETWORK_INET_DGRAM_SEND]        = "inet_dgram_send",
65            [CCS_MAC_NETWORK_INET_DGRAM_RECV]        = "inet_dgram_recv",
66            [CCS_MAC_NETWORK_INET_RAW_BIND]          = "inet_raw_bind",
67            [CCS_MAC_NETWORK_INET_RAW_SEND]          = "inet_raw_send",
68            [CCS_MAC_NETWORK_INET_RAW_RECV]          = "inet_raw_recv",
69            [CCS_MAC_NETWORK_UNIX_STREAM_BIND]       = "unix_stream_bind",
70            [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN]     = "unix_stream_listen",
71            [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT]    = "unix_stream_connect",
72            [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT]     = "unix_stream_accept",
73            [CCS_MAC_NETWORK_UNIX_DGRAM_BIND]        = "unix_dgram_bind",
74            [CCS_MAC_NETWORK_UNIX_DGRAM_SEND]        = "unix_dgram_send",
75            [CCS_MAC_NETWORK_UNIX_DGRAM_RECV]        = "unix_dgram_recv",
76            [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND]    = "unix_seqpacket_bind",
77            [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN]  = "unix_seqpacket_listen",
78            [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect",
79            [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT]  = "unix_seqpacket_accept",
80            /* CONFIG::ipc group */
81            [CCS_MAC_SIGNAL] = "signal",
82            /* CONFIG::capability group */
83            [CCS_MAC_CAPABILITY_USE_ROUTE_SOCKET]  = "use_route",
84            [CCS_MAC_CAPABILITY_USE_PACKET_SOCKET] = "use_packet",
85            [CCS_MAC_CAPABILITY_SYS_REBOOT]        = "SYS_REBOOT",
86            [CCS_MAC_CAPABILITY_SYS_VHANGUP]       = "SYS_VHANGUP",
87            [CCS_MAC_CAPABILITY_SYS_SETTIME]       = "SYS_TIME",
88            [CCS_MAC_CAPABILITY_SYS_NICE]          = "SYS_NICE",
89            [CCS_MAC_CAPABILITY_SYS_SETHOSTNAME]   = "SYS_SETHOSTNAME",
90            [CCS_MAC_CAPABILITY_USE_KERNEL_MODULE] = "use_kernel_module",
91            [CCS_MAC_CAPABILITY_SYS_KEXEC_LOAD]    = "SYS_KEXEC_LOAD",
92            [CCS_MAC_CAPABILITY_SYS_PTRACE]        = "SYS_PTRACE",
93            /* CONFIG group */
94            [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_FILE]       = "file",
95            [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_NETWORK]    = "network",
96            [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_MISC]       = "misc",
97            [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_IPC]        = "ipc",
98            [CCS_MAX_MAC_INDEX + CCS_MAC_CATEGORY_CAPABILITY] = "capability",
99    };
100    
101    /* String table for path operation. */
102    const char * const ccs_path_keyword[CCS_MAX_PATH_OPERATION] = {
103            [CCS_TYPE_EXECUTE]    = "execute",
104            [CCS_TYPE_READ]       = "read",
105            [CCS_TYPE_WRITE]      = "write",
106            [CCS_TYPE_APPEND]     = "append",
107            [CCS_TYPE_UNLINK]     = "unlink",
108            [CCS_TYPE_GETATTR]    = "getattr",
109            [CCS_TYPE_RMDIR]      = "rmdir",
110            [CCS_TYPE_TRUNCATE]   = "truncate",
111            [CCS_TYPE_SYMLINK]    = "symlink",
112            [CCS_TYPE_CHROOT]     = "chroot",
113            [CCS_TYPE_UMOUNT]     = "unmount",
114    };
115    
116    /* String table for categories. */
117    static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
118            [CCS_MAC_CATEGORY_FILE]       = "file",
119            [CCS_MAC_CATEGORY_NETWORK]    = "network",
120            [CCS_MAC_CATEGORY_MISC]       = "misc",
121            [CCS_MAC_CATEGORY_IPC]        = "ipc",
122            [CCS_MAC_CATEGORY_CAPABILITY] = "capability",
123    };
124    
125    /* String table for conditions. */
126    const char * const ccs_condition_keyword[CCS_MAX_CONDITION_KEYWORD] = {
127            [CCS_TASK_UID]             = "task.uid",
128            [CCS_TASK_EUID]            = "task.euid",
129            [CCS_TASK_SUID]            = "task.suid",
130            [CCS_TASK_FSUID]           = "task.fsuid",
131            [CCS_TASK_GID]             = "task.gid",
132            [CCS_TASK_EGID]            = "task.egid",
133            [CCS_TASK_SGID]            = "task.sgid",
134            [CCS_TASK_FSGID]           = "task.fsgid",
135            [CCS_TASK_PID]             = "task.pid",
136            [CCS_TASK_PPID]            = "task.ppid",
137            [CCS_EXEC_ARGC]            = "exec.argc",
138            [CCS_EXEC_ENVC]            = "exec.envc",
139            [CCS_TYPE_IS_SOCKET]       = "socket",
140            [CCS_TYPE_IS_SYMLINK]      = "symlink",
141            [CCS_TYPE_IS_FILE]         = "file",
142            [CCS_TYPE_IS_BLOCK_DEV]    = "block",
143            [CCS_TYPE_IS_DIRECTORY]    = "directory",
144            [CCS_TYPE_IS_CHAR_DEV]     = "char",
145            [CCS_TYPE_IS_FIFO]         = "fifo",
146            [CCS_MODE_SETUID]          = "setuid",
147            [CCS_MODE_SETGID]          = "setgid",
148            [CCS_MODE_STICKY]          = "sticky",
149            [CCS_MODE_OWNER_READ]      = "owner_read",
150            [CCS_MODE_OWNER_WRITE]     = "owner_write",
151            [CCS_MODE_OWNER_EXECUTE]   = "owner_execute",
152            [CCS_MODE_GROUP_READ]      = "group_read",
153            [CCS_MODE_GROUP_WRITE]     = "group_write",
154            [CCS_MODE_GROUP_EXECUTE]   = "group_execute",
155            [CCS_MODE_OTHERS_READ]     = "others_read",
156            [CCS_MODE_OTHERS_WRITE]    = "others_write",
157            [CCS_MODE_OTHERS_EXECUTE]  = "others_execute",
158            [CCS_TASK_TYPE]            = "task.type",
159            [CCS_TASK_EXECUTE_HANDLER] = "execute_handler",
160            [CCS_EXEC_REALPATH]        = "exec.realpath",
161            [CCS_SYMLINK_TARGET]       = "symlink.target",
162            [CCS_PATH1_UID]            = "path1.uid",
163            [CCS_PATH1_GID]            = "path1.gid",
164            [CCS_PATH1_INO]            = "path1.ino",
165            [CCS_PATH1_MAJOR]          = "path1.major",
166            [CCS_PATH1_MINOR]          = "path1.minor",
167            [CCS_PATH1_PERM]           = "path1.perm",
168            [CCS_PATH1_TYPE]           = "path1.type",
169            [CCS_PATH1_DEV_MAJOR]      = "path1.dev_major",
170            [CCS_PATH1_DEV_MINOR]      = "path1.dev_minor",
171            [CCS_PATH2_UID]            = "path2.uid",
172            [CCS_PATH2_GID]            = "path2.gid",
173            [CCS_PATH2_INO]            = "path2.ino",
174            [CCS_PATH2_MAJOR]          = "path2.major",
175            [CCS_PATH2_MINOR]          = "path2.minor",
176            [CCS_PATH2_PERM]           = "path2.perm",
177            [CCS_PATH2_TYPE]           = "path2.type",
178            [CCS_PATH2_DEV_MAJOR]      = "path2.dev_major",
179            [CCS_PATH2_DEV_MINOR]      = "path2.dev_minor",
180            [CCS_PATH1_PARENT_UID]     = "path1.parent.uid",
181            [CCS_PATH1_PARENT_GID]     = "path1.parent.gid",
182            [CCS_PATH1_PARENT_INO]     = "path1.parent.ino",
183            [CCS_PATH1_PARENT_PERM]    = "path1.parent.perm",
184            [CCS_PATH2_PARENT_UID]     = "path2.parent.uid",
185            [CCS_PATH2_PARENT_GID]     = "path2.parent.gid",
186            [CCS_PATH2_PARENT_INO]     = "path2.parent.ino",
187            [CCS_PATH2_PARENT_PERM]    = "path2.parent.perm",
188  };  };
189    
190  /* String table for /proc/ccs/profile */  /* String table for PREFERENCE keyword. */
191  static const char *ccs_mac_keywords[CCS_MAX_MAC_INDEX +  static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
192                                      CCS_MAX_CAPABILITY_INDEX +          [CCS_PREF_MAX_GRANT_LOG]      = "max_grant_log",
193                                      CCS_MAX_MAC_CATEGORY_INDEX] = {          [CCS_PREF_MAX_REJECT_LOG]     = "max_reject_log",
194          [CCS_MAC_FILE_EXECUTE]          [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
195          = "file::execute",          [CCS_PREF_ENFORCING_PENALTY]  = "enforcing_penalty",
         [CCS_MAC_FILE_OPEN]  
         = "file::open",  
         [CCS_MAC_FILE_CREATE]  
         = "file::create",  
         [CCS_MAC_FILE_UNLINK]  
         = "file::unlink",  
         [CCS_MAC_FILE_MKDIR]  
         = "file::mkdir",  
         [CCS_MAC_FILE_RMDIR]  
         = "file::rmdir",  
         [CCS_MAC_FILE_MKFIFO]  
         = "file::mkfifo",  
         [CCS_MAC_FILE_MKSOCK]  
         = "file::mksock",  
         [CCS_MAC_FILE_TRUNCATE]  
         = "file::truncate",  
         [CCS_MAC_FILE_SYMLINK]  
         = "file::symlink",  
         [CCS_MAC_FILE_MKBLOCK]  
         = "file::mkblock",  
         [CCS_MAC_FILE_MKCHAR]  
         = "file::mkchar",  
         [CCS_MAC_FILE_LINK]  
         = "file::link",  
         [CCS_MAC_FILE_RENAME]  
         = "file::rename",  
         [CCS_MAC_FILE_CHMOD]  
         = "file::chmod",  
         [CCS_MAC_FILE_CHOWN]  
         = "file::chown",  
         [CCS_MAC_FILE_CHGRP]  
         = "file::chgrp",  
         [CCS_MAC_FILE_IOCTL]  
         = "file::ioctl",  
         [CCS_MAC_FILE_CHROOT]  
         = "file::chroot",  
         [CCS_MAC_FILE_MOUNT]  
         = "file::mount",  
         [CCS_MAC_FILE_UMOUNT]  
         = "file::umount",  
         [CCS_MAC_FILE_PIVOT_ROOT]  
         = "file::pivot_root",  
         [CCS_MAC_ENVIRON]  
         = "misc::env",  
         [CCS_MAC_NETWORK_INET_STREAM_BIND]  
         = "network::inet_stream_bind",  
         [CCS_MAC_NETWORK_INET_STREAM_LISTEN]  
         = "network::inet_stream_listen",  
         [CCS_MAC_NETWORK_INET_STREAM_CONNECT]  
         = "network::inet_stream_connect",  
         [CCS_MAC_NETWORK_INET_STREAM_ACCEPT]  
         = "network::inet_stream_accept",  
         [CCS_MAC_NETWORK_INET_DGRAM_BIND]  
         = "network::inet_dgram_bind",  
         [CCS_MAC_NETWORK_INET_DGRAM_SEND]  
         = "network::inet_dgram_send",  
         [CCS_MAC_NETWORK_INET_DGRAM_RECV]  
         = "network::inet_dgram_recv",  
         [CCS_MAC_NETWORK_INET_RAW_BIND]  
         = "network::inet_raw_bind",  
         [CCS_MAC_NETWORK_INET_RAW_SEND]  
         = "network::inet_raw_send",  
         [CCS_MAC_NETWORK_INET_RAW_RECV]  
         = "network::inet_raw_recv",  
         [CCS_MAC_NETWORK_UNIX_STREAM_BIND]  
         = "network::unix_stream_bind",  
         [CCS_MAC_NETWORK_UNIX_STREAM_LISTEN]  
         = "network::unix_stream_listen",  
         [CCS_MAC_NETWORK_UNIX_STREAM_CONNECT]  
         = "network::unix_stream_connect",  
         [CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT]  
         = "network::unix_stream_accept",  
         [CCS_MAC_NETWORK_UNIX_DGRAM_BIND]  
         = "network::unix_dgram_bind",  
         [CCS_MAC_NETWORK_UNIX_DGRAM_SEND]  
         = "network::unix_dgram_send",  
         [CCS_MAC_NETWORK_UNIX_DGRAM_RECV]  
         = "network::unix_dgram_recv",  
         [CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND]  
         = "network::unix_seqpacket_bind",  
         [CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN]  
         = "network::unix_seqpacket_listen",  
         [CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT]  
         = "network::unix_seqpacket_connect",  
         [CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT]  
         = "network::unix_seqpacket_accept",  
         [CCS_MAC_SIGNAL]  
         = "ipc::signal",  
         [CCS_MAX_MAC_INDEX + CCS_USE_ROUTE_SOCKET]  
         = "capability::use_route",  
         [CCS_MAX_MAC_INDEX + CCS_USE_PACKET_SOCKET]  
         = "capability::use_packet",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_REBOOT]  
         = "capability::SYS_REBOOT",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_VHANGUP]  
         = "capability::SYS_VHANGUP",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_SETTIME]  
         = "capability::SYS_TIME",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_NICE]  
         = "capability::SYS_NICE",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_SETHOSTNAME]  
         = "capability::SYS_SETHOSTNAME",  
         [CCS_MAX_MAC_INDEX + CCS_USE_KERNEL_MODULE]  
         = "capability::use_kernel_module",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_KEXEC_LOAD]  
         = "capability::SYS_KEXEC_LOAD",  
         [CCS_MAX_MAC_INDEX + CCS_SYS_PTRACE]  
         = "capability::SYS_PTRACE",  
         [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX  
          + CCS_MAC_CATEGORY_FILE] = "file",  
         [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX  
          + CCS_MAC_CATEGORY_NETWORK] = "network",  
         [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX  
          + CCS_MAC_CATEGORY_MISC] = "misc",  
         [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX  
          + CCS_MAC_CATEGORY_IPC] = "ipc",  
         [CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX  
          + CCS_MAC_CATEGORY_CAPABILITY] = "capability",  
196  };  };
197    
198  /* Permit policy management by non-root user? */  /* Permit policy management by non-root user? */
199  static bool ccs_manage_by_non_root;  static bool ccs_manage_by_non_root;
200    
201  /**  /**
  * ccs_cap2keyword - Convert capability operation to capability name.  
  *  
  * @operation: The capability index.  
  *  
  * Returns the name of the specified capability's name.  
  */  
 const char *ccs_cap2keyword(const u8 operation)  
 {  
         return operation < CCS_MAX_CAPABILITY_INDEX  
                 ? ccs_mac_keywords[CCS_MAX_MAC_INDEX + operation] + 12 : NULL;  
 }  
   
 /**  
202   * ccs_yesno - Return "yes" or "no".   * ccs_yesno - Return "yes" or "no".
203   *   *
204   * @value: Bool value.   * @value: Bool value.
205     *
206     * Returns "yes" if @value is not 0, "no" otherwise.
207   */   */
208  static const char *ccs_yesno(const unsigned int value)  static const char *ccs_yesno(const unsigned int value)
209  {  {
210          return value ? "yes" : "no";          return value ? "yes" : "no";
211  }  }
212    
213    /* Prototype fpr ccs_addprintf(). */
214    static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
215            __attribute__ ((format(printf, 3, 4)));
216    
217    /**
218     * ccs_addprintf - snprint()-like-strncat().
219     *
220     * @buffer: Buffer to write to. Must be '\0'-terminated.
221     * @len:    Size of @buffer.
222     * @fmt:    The printf()'s format string, followed by parameters.
223     *
224     * Returns nothing.
225     */
226  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
227  {  {
228          va_list args;          va_list args;
# Line 207  static void ccs_addprintf(char *buffer, Line 235  static void ccs_addprintf(char *buffer,
235  /**  /**
236   * ccs_flush - Flush queued string to userspace's buffer.   * ccs_flush - Flush queued string to userspace's buffer.
237   *   *
238   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
239   *   *
240   * Returns true if all data was flushed, false otherwise.   * Returns true if all data was flushed, false otherwise.
241   */   */
# Line 256  static bool ccs_flush(struct ccs_io_buff Line 284  static bool ccs_flush(struct ccs_io_buff
284   * 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.
285   * This means that char[] allocated on stack memory cannot be passed to   * This means that char[] allocated on stack memory cannot be passed to
286   * this function. Use ccs_io_printf() for char[] allocated on stack memory.   * this function. Use ccs_io_printf() for char[] allocated on stack memory.
287     *
288     * Returns nothing.
289   */   */
290  static void ccs_set_string(struct ccs_io_buffer *head, const char *string)  static void ccs_set_string(struct ccs_io_buffer *head, const char *string)
291  {  {
# Line 271  static void ccs_set_string(struct ccs_io Line 301  static void ccs_set_string(struct ccs_io
301   *   *
302   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
303   * @fmt:  The printf()'s format string, followed by parameters.   * @fmt:  The printf()'s format string, followed by parameters.
304     *
305     * Returns nothing.
306   */   */
307  void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)  void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
308  {  {
# Line 291  void ccs_io_printf(struct ccs_io_buffer Line 323  void ccs_io_printf(struct ccs_io_buffer
323          ccs_set_string(head, head->read_buf + pos);          ccs_set_string(head, head->read_buf + pos);
324  }  }
325    
326    /**
327     * ccs_set_space - Put a space to "struct ccs_io_buffer" structure.
328     *
329     * @head: Pointer to "struct ccs_io_buffer".
330     *
331     * Returns nothing.
332     */
333  static void ccs_set_space(struct ccs_io_buffer *head)  static void ccs_set_space(struct ccs_io_buffer *head)
334  {  {
335          ccs_set_string(head, " ");          ccs_set_string(head, " ");
336  }  }
337    
338    /**
339     * ccs_set_lf - Put a line feed to "struct ccs_io_buffer" structure.
340     *
341     * @head: Pointer to "struct ccs_io_buffer".
342     *
343     * Returns nothing.
344     */
345  static bool ccs_set_lf(struct ccs_io_buffer *head)  static bool ccs_set_lf(struct ccs_io_buffer *head)
346  {  {
347          ccs_set_string(head, "\n");          ccs_set_string(head, "\n");
# Line 328  static struct ccs_profile *ccs_assign_pr Line 374  static struct ccs_profile *ccs_assign_pr
374                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
375                  memset(ptr->config, CCS_CONFIG_USE_DEFAULT,                  memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
376                         sizeof(ptr->config));                         sizeof(ptr->config));
377                    ptr->pref[CCS_PREF_MAX_GRANT_LOG] =
378                            CONFIG_CCSECURITY_MAX_GRANT_LOG;
379                    ptr->pref[CCS_PREF_MAX_REJECT_LOG] =
380                            CONFIG_CCSECURITY_MAX_REJECT_LOG;
381                    ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
382                            CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
383                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
384                  ccs_profile_ptr[profile] = ptr;                  ccs_profile_ptr[profile] = ptr;
385                  entry = NULL;                  entry = NULL;
386          }          }
387          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
388   out:  out:
389          kfree(entry);          kfree(entry);
390          return ptr;          return ptr;
391  }  }
392    
393  /**  /**
394   * ccs_check_profile - Check all profiles currently assigned to domains are defined.   * ccs_check_profile - Check all profiles currently assigned to domains are defined.
395     *
396     * Returns nothing.
397   */   */
398  static void ccs_check_profile(void)  static void ccs_check_profile(void)
399  {  {
400          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
401          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
402          ccs_policy_loaded = true;          ccs_policy_loaded = true;
403          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
404                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
405                  if (ccs_profile_ptr[profile])                  if (ccs_profile_ptr[profile])
406                          continue;                          continue;
407                    printk(KERN_ERR "You need to define profile %u before using it.\n",
408                           profile);
409                    printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
410                           "for more information.\n");
411                  panic("Profile %u (used by '%s') not defined.\n",                  panic("Profile %u (used by '%s') not defined.\n",
412                        profile, domain->domainname->name);                        profile, domain->domainname->name);
413          }          }
414          ccs_read_unlock(idx);          ccs_read_unlock(idx);
415          if (ccs_profile_version != 20100903)          if (ccs_profile_version != 20100903) {
416                    printk(KERN_ERR "You need to install userland programs for "
417                           "TOMOYO 1.8 and initialize policy configuration.\n");
418                    printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
419                           "for more information.\n");
420                  panic("Profile version %u is not supported.\n",                  panic("Profile version %u is not supported.\n",
421                        ccs_profile_version);                        ccs_profile_version);
422          printk(KERN_INFO "CCSecurity: 1.8.0-pre   2010/09/01\n");          }
423            printk(KERN_INFO "CCSecurity: 1.8.0-pre   2010/10/22\n");
424          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
425  }  }
426    
# Line 377  struct ccs_profile *ccs_profile(const u8 Line 440  struct ccs_profile *ccs_profile(const u8
440          return ptr;          return ptr;
441  }  }
442    
443    /**
444     * ccs_find_yesno - Find values for specified keyword.
445     *
446     * @string: String to check.
447     * @find:   Name of keyword.
448     *
449     * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
450     */
451  static s8 ccs_find_yesno(const char *string, const char *find)  static s8 ccs_find_yesno(const char *string, const char *find)
452  {  {
453          const char *cp = strstr(string, find);          const char *cp = strstr(string, find);
# Line 390  static s8 ccs_find_yesno(const char *str Line 461  static s8 ccs_find_yesno(const char *str
461          return -1;          return -1;
462  }  }
463    
464  static void ccs_set_bool(bool *b, const char *string, const char *find)  /**
465  {   * ccs_set_uint - Set value for specified preference.
466          switch (ccs_find_yesno(string, find)) {   *
467          case 1:   * @i:      Pointer to "unsigned int".
468                  *b = true;   * @string: String to check.
469                  break;   * @find:   Name of keyword.
470          case 0:   *
471                  *b = false;   * Returns nothing.
472                  break;   */
         }  
 }  
   
473  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)
474  {  {
475          const char *cp = strstr(string, find);          const char *cp = strstr(string, find);
# Line 409  static void ccs_set_uint(unsigned int *i Line 477  static void ccs_set_uint(unsigned int *i
477                  sscanf(cp + strlen(find), "=%u", i);                  sscanf(cp + strlen(find), "=%u", i);
478  }  }
479    
480  static int ccs_set_pref(char *data)  /**
481  {   * ccs_set_mode - Set mode for specified profile.
482          if (ccs_str_starts(&data, "audit")) {   *
483  #ifdef CONFIG_CCSECURITY_AUDIT   * @name:    Name of functionality.
484                  ccs_set_uint(&ccs_preference.audit_max_grant_log, data,   * @value:   Mode for @name.
485                               "max_grant_log");   * @profile: Pointer to "struct ccs_profile".
486                  ccs_set_uint(&ccs_preference.audit_max_reject_log, data,   *
487                               "max_reject_log");   * Returns 0 on success, negative value otherwise.
488  #endif   */
                 ccs_set_bool(&ccs_preference.audit_task_info, data,  
                              "task_info");  
                 ccs_set_bool(&ccs_preference.audit_path_info, data,  
                              "path_info");  
         } else if (ccs_str_starts(&data, "enforcing")) {  
                 ccs_set_bool(&ccs_preference.enforcing_verbose, data,  
                              "verbose");  
                 ccs_set_uint(&ccs_preference.enforcing_penalty, data,  
                              "penalty");  
         } else if (ccs_str_starts(&data, "permissive")) {  
                 ccs_set_bool(&ccs_preference.permissive_verbose, data,  
                              "verbose");  
         } else if (ccs_str_starts(&data, "learning")) {  
                 ccs_set_bool(&ccs_preference.learning_verbose, data,  
                              "verbose");  
                 ccs_set_uint(&ccs_preference.learning_max_entry, data,  
                              "max_entry");  
                 ccs_set_bool(&ccs_preference.learning_exec_realpath, data,  
                              "exec.realpath");  
                 ccs_set_bool(&ccs_preference.learning_exec_argv0, data,  
                              "exec.argv0");  
                 ccs_set_bool(&ccs_preference.learning_symlink_target, data,  
                              "symlink.target");  
         } else  
                 return -EINVAL;  
         return 0;  
 }  
   
489  static int ccs_set_mode(char *name, const char *value,  static int ccs_set_mode(char *name, const char *value,
490                          struct ccs_profile *profile)                          struct ccs_profile *profile)
491  {  {
492          u8 i;          u8 i;
493          u8 config;          u8 config;
494          if (!strcmp(name, "CONFIG")) {          if (!strcmp(name, "CONFIG")) {
495                  i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  i = CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
                         + CCS_MAX_MAC_CATEGORY_INDEX;  
496                  config = profile->default_config;                  config = profile->default_config;
497          } else if (ccs_str_starts(&name, "CONFIG::")) {          } else if (ccs_str_starts(&name, "CONFIG::")) {
498                  config = 0;                  config = 0;
499                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX;
500                               + CCS_MAX_MAC_CATEGORY_INDEX; i++) {                       i++) {
501                          if (strcmp(name, ccs_mac_keywords[i]))                          int len = 0;
502                            if (i < CCS_MAX_MAC_INDEX) {
503                                    const u8 c = ccs_index2category[i];
504                                    const char *category =
505                                            ccs_category_keywords[c];
506                                    len = strlen(category);
507                                    if (strncmp(name, category, len) ||
508                                        name[len++] != ':' || name[len++] != ':')
509                                            continue;
510                            }
511                            if (strcmp(name + len, ccs_mac_keywords[i]))
512                                  continue;                                  continue;
513                          config = profile->config[i];                          config = profile->config[i];
514                          break;                          break;
515                  }                  }
516                  if (i == CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  if (i == CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
                     + CCS_MAX_MAC_CATEGORY_INDEX)  
517                          return -EINVAL;                          return -EINVAL;
518          } else {          } else {
519                  return -EINVAL;                  return -EINVAL;
# Line 482  static int ccs_set_mode(char *name, cons Line 530  static int ccs_set_mode(char *name, cons
530                                   */                                   */
531                                  config = (config & ~7) | mode;                                  config = (config & ~7) | mode;
532                  if (config != CCS_CONFIG_USE_DEFAULT) {                  if (config != CCS_CONFIG_USE_DEFAULT) {
 #ifdef CONFIG_CCSECURITY_AUDIT  
533                          switch (ccs_find_yesno(value, "grant_log")) {                          switch (ccs_find_yesno(value, "grant_log")) {
534                          case 1:                          case 1:
535                                  config |= CCS_CONFIG_WANT_GRANT_LOG;                                  config |= CCS_CONFIG_WANT_GRANT_LOG;
# Line 499  static int ccs_set_mode(char *name, cons Line 546  static int ccs_set_mode(char *name, cons
546                                  config &= ~CCS_CONFIG_WANT_REJECT_LOG;                                  config &= ~CCS_CONFIG_WANT_REJECT_LOG;
547                                  break;                                  break;
548                          }                          }
 #endif  
549                  }                  }
550          }          }
551          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
             + CCS_MAX_MAC_CATEGORY_INDEX)  
552                  profile->config[i] = config;                  profile->config[i] = config;
553          else if (config != CCS_CONFIG_USE_DEFAULT)          else if (config != CCS_CONFIG_USE_DEFAULT)
554                  profile->default_config = config;                  profile->default_config = config;
# Line 525  static int ccs_write_profile(struct ccs_ Line 570  static int ccs_write_profile(struct ccs_
570          struct ccs_profile *profile;          struct ccs_profile *profile;
571          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)
572                  return 0;                  return 0;
         if (ccs_str_starts(&data, "PREFERENCE::"))  
                 return ccs_set_pref(data);  
573          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
574          if (*cp != '-')          if (*cp != '-')
575                  return -EINVAL;                  return -EINVAL;
# Line 544  static int ccs_write_profile(struct ccs_ Line 587  static int ccs_write_profile(struct ccs_
587                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
588                  return 0;                  return 0;
589          }          }
590            if (!strcmp(data, "PREFERENCE")) {
591                    for (i = 0; i < CCS_MAX_PREF; i++)
592                            ccs_set_uint(&profile->pref[i], cp,
593                                         ccs_pref_keywords[i]);
594                    return 0;
595            }
596          return ccs_set_mode(data, cp, profile);          return ccs_set_mode(data, cp, profile);
597  }  }
598    
599  static void ccs_print_preference(struct ccs_io_buffer *head)  /**
600  {   * ccs_print_config - Print mode for specified functionality.
601          ccs_io_printf(head, "PREFERENCE::%s={ "   *
602  #ifdef CONFIG_CCSECURITY_AUDIT   * @head:   Pointer to "struct ccs_io_buffer".
603                        "max_grant_log=%u max_reject_log=%u "   * @config: Mode for that functionality.
604  #endif   *
605                        "task_info=%s path_info=%s }\n", "audit",   * Returns nothing.
606  #ifdef CONFIG_CCSECURITY_AUDIT   *
607                        ccs_preference.audit_max_grant_log,   * Caller prints functionality's name.
608                        ccs_preference.audit_max_reject_log,   */
 #endif  
                       ccs_yesno(ccs_preference.audit_task_info),  
                       ccs_yesno(ccs_preference.audit_path_info));  
         ccs_io_printf(head, "PREFERENCE::%s={ verbose=%s max_entry=%u "  
                       "exec.realpath=%s exec.argv0=%s symlink.target=%s }\n",  
                       "learning", ccs_yesno(ccs_preference.learning_verbose),  
                       ccs_preference.learning_max_entry,  
                       ccs_yesno(ccs_preference.learning_exec_realpath),  
                       ccs_yesno(ccs_preference.learning_exec_argv0),  
                       ccs_yesno(ccs_preference.learning_symlink_target));  
         ccs_io_printf(head, "PREFERENCE::%s={ verbose=%s }\n", "permissive",  
                       ccs_yesno(ccs_preference.permissive_verbose));  
         ccs_io_printf(head, "PREFERENCE::%s={ verbose=%s penalty=%u }\n",  
                       "enforcing", ccs_yesno(ccs_preference.enforcing_verbose),  
                       ccs_preference.enforcing_penalty);  
 }  
   
609  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)
610  {  {
611          ccs_io_printf(head, "={ mode=%s", ccs_mode[config & 3]);          ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
612  #ifdef CONFIG_CCSECURITY_AUDIT                        ccs_mode[config & 3],
         ccs_io_printf(head, " grant_log=%s reject_log=%s",  
613                        ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),                        ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
614                        ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));                        ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
 #endif  
         ccs_set_string(head, " }\n");  
615  }  }
616    
617  /**  /**
# Line 594  static void ccs_read_profile(struct ccs_ Line 623  static void ccs_read_profile(struct ccs_
623  {  {
624          u8 index;          u8 index;
625          const struct ccs_profile *profile;          const struct ccs_profile *profile;
626   next:  next:
627          index = head->r.index;          index = head->r.index;
628          profile = ccs_profile_ptr[index];          profile = ccs_profile_ptr[index];
629          switch (head->r.step) {          switch (head->r.step) {
630          case 0:          case 0:
631                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");
                 ccs_print_preference(head);  
632                  head->r.step++;                  head->r.step++;
633                  break;                  break;
634          case 1:          case 1:
# Line 614  static void ccs_read_profile(struct ccs_ Line 642  static void ccs_read_profile(struct ccs_
642                  break;                  break;
643          case 2:          case 2:
644                  {                  {
645                            u8 i;
646                          const struct ccs_path_info *comment = profile->comment;                          const struct ccs_path_info *comment = profile->comment;
647                          ccs_io_printf(head, "%u-COMMENT=", index);                          ccs_io_printf(head, "%u-COMMENT=", index);
648                          ccs_set_string(head, comment ? comment->name : "");                          ccs_set_string(head, comment ? comment->name : "");
649                          ccs_set_lf(head);                          ccs_set_lf(head);
650                            ccs_io_printf(head, "%u-PREFERENCE={ ", index);
651                            for (i = 0; i < CCS_MAX_PREF; i++)
652                                    ccs_io_printf(head, "%s=%u ",
653                                                  ccs_pref_keywords[i],
654                                                  profile->pref[i]);
655                            ccs_set_string(head, " }\n");
656                          head->r.step++;                          head->r.step++;
657                  }                  }
658                  break;                  break;
# Line 631  static void ccs_read_profile(struct ccs_ Line 666  static void ccs_read_profile(struct ccs_
666                  break;                  break;
667          case 4:          case 4:
668                  for ( ; head->r.bit < CCS_MAX_MAC_INDEX                  for ( ; head->r.bit < CCS_MAX_MAC_INDEX
                               + CCS_MAX_CAPABILITY_INDEX  
669                                + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {                                + CCS_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
670                          const u8 i = head->r.bit;                          const u8 i = head->r.bit;
671                          const u8 config = profile->config[i];                          const u8 config = profile->config[i];
672                          if (config == CCS_CONFIG_USE_DEFAULT)                          if (config == CCS_CONFIG_USE_DEFAULT)
673                                  continue;                                  continue;
674                          ccs_io_printf(head, "%u-%s%s", index, "CONFIG::",                          if (i < CCS_MAX_MAC_INDEX)
675                                        ccs_mac_keywords[i]);                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
676                                                  ccs_category_keywords
677                                                  [ccs_index2category[i]],
678                                                  ccs_mac_keywords[i]);
679                            else
680                                    ccs_io_printf(head, "%u-CONFIG::%s", index,
681                                                  ccs_mac_keywords[i]);
682                          ccs_print_config(head, config);                          ccs_print_config(head, config);
683                          head->r.bit++;                          head->r.bit++;
684                          break;                          break;
685                  }                  }
686                  if (head->r.bit == CCS_MAX_MAC_INDEX                  if (head->r.bit == CCS_MAX_MAC_INDEX
                     + CCS_MAX_CAPABILITY_INDEX  
687                      + CCS_MAX_MAC_CATEGORY_INDEX) {                      + CCS_MAX_MAC_CATEGORY_INDEX) {
688                          head->r.index++;                          head->r.index++;
689                          head->r.step = 1;                          head->r.step = 1;
# Line 655  static void ccs_read_profile(struct ccs_ Line 694  static void ccs_read_profile(struct ccs_
694                  goto next;                  goto next;
695  }  }
696    
697    /**
698     * ccs_same_manager - Check for duplicated "struct ccs_manager" entry.
699     *
700     * @a: Pointer to "struct ccs_acl_head".
701     * @b: Pointer to "struct ccs_acl_head".
702     *
703     * Returns true if @a and @b are duplicated, false otherwise.
704     */
705  static bool ccs_same_manager(const struct ccs_acl_head *a,  static bool ccs_same_manager(const struct ccs_acl_head *a,
706                               const struct ccs_acl_head *b)                               const struct ccs_acl_head *b)
707  {  {
# Line 702  static int ccs_update_manager_entry(cons Line 749  static int ccs_update_manager_entry(cons
749  static int ccs_write_manager(struct ccs_io_buffer *head)  static int ccs_write_manager(struct ccs_io_buffer *head)
750  {  {
751          char *data = head->write_buf;          char *data = head->write_buf;
752          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);          bool is_delete = ccs_str_starts(&data, "delete ");
753          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
754                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !is_delete;
755                  return 0;                  return 0;
# Line 746  static bool ccs_manager(void) Line 793  static bool ccs_manager(void)
793  {  {
794          struct ccs_manager *ptr;          struct ccs_manager *ptr;
795          const char *exe;          const char *exe;
796          struct task_struct *task = current;          struct ccs_security *task = ccs_current_security();
797          const struct ccs_path_info *domainname          const struct ccs_path_info *domainname
798                  = ccs_current_domain()->domainname;                  = ccs_current_domain()->domainname;
799          bool found = false;          bool found = false;
# Line 757  static bool ccs_manager(void) Line 804  static bool ccs_manager(void)
804          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
805                  return false;                  return false;
806          exe = ccs_get_exe();          exe = ccs_get_exe();
807          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
808                                  head.list) {                                   head.list, &ccs_ss) {
809                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
810                          continue;                          continue;
811                  if (ptr->is_domain) {                  if (ptr->is_domain) {
# Line 842  static bool ccs_select_one(struct ccs_io Line 889  static bool ccs_select_one(struct ccs_io
889          return true;          return true;
890  }  }
891    
892    /**
893     * ccs_same_handler_acl - Check for duplicated "struct ccs_handler_acl" entry.
894     *
895     * @a: Pointer to "struct ccs_acl_info".
896     * @b: Pointer to "struct ccs_acl_info".
897     *
898     * Returns true if @a and @b are duplicated, false otherwise.
899     */
900  static bool ccs_same_handler_acl(const struct ccs_acl_info *a,  static bool ccs_same_handler_acl(const struct ccs_acl_info *a,
901                                   const struct ccs_acl_info *b)                                   const struct ccs_acl_info *b)
902  {  {
# Line 850  static bool ccs_same_handler_acl(const s Line 905  static bool ccs_same_handler_acl(const s
905          return p1->handler == p2->handler;          return p1->handler == p2->handler;
906  }  }
907    
908    /**
909     * ccs_same_task_acl - Check for duplicated "struct ccs_task_acl" entry.
910     *
911     * @a: Pointer to "struct ccs_acl_info".
912     * @b: Pointer to "struct ccs_acl_info".
913     *
914     * Returns true if @a and @b are duplicated, false otherwise.
915     */
916  static bool ccs_same_task_acl(const struct ccs_acl_info *a,  static bool ccs_same_task_acl(const struct ccs_acl_info *a,
917                                const struct ccs_acl_info *b)                                const struct ccs_acl_info *b)
918  {  {
# Line 909  static int ccs_write_task(struct ccs_acl Line 972  static int ccs_write_task(struct ccs_acl
972          return error;          return error;
973  }  }
974    
975    /**
976     * ccs_write_domain2 - Write domain policy.
977     *
978     * @data:      Policy to be interpreted.
979     * @domain:    Pointer to "struct ccs_domain_info".
980     * @is_delete: True if it is a delete request.
981     *
982     * Returns 0 on success, negative value otherwise.
983     */
984  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,
985                               const bool is_delete)                               const bool is_delete)
986  {  {
# Line 938  static int ccs_write_domain2(char *data, Line 1010  static int ccs_write_domain2(char *data,
1010          return -EINVAL;          return -EINVAL;
1011  }  }
1012    
1013  static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {  /* String table for domain flags. */
1014          [CCS_DIF_QUOTA_WARNED] = CCS_KEYWORD_QUOTA_EXCEEDED "\n",  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1015          [CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n"          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",
1016            [CCS_DIF_TRANSITION_FAILED] = "transition_failed\n",
1017  };  };
1018            
1019  /**  /**
1020   * ccs_write_domain - Write domain policy.   * ccs_write_domain - Write domain policy.
1021   *   *
# Line 957  static int ccs_write_domain(struct ccs_i Line 1030  static int ccs_write_domain(struct ccs_i
1030          bool is_delete = false;          bool is_delete = false;
1031          bool is_select = false;          bool is_select = false;
1032          unsigned int profile;          unsigned int profile;
1033          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))          if (ccs_str_starts(&data, "delete "))
1034                  is_delete = true;                  is_delete = true;
1035          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))          else if (ccs_str_starts(&data, "select "))
1036                  is_select = true;                  is_select = true;
1037          if (is_select && ccs_select_one(head, data))          if (is_select && ccs_select_one(head, data))
1038                  return 0;                  return 0;
# Line 980  static int ccs_write_domain(struct ccs_i Line 1053  static int ccs_write_domain(struct ccs_i
1053          if (!domain)          if (!domain)
1054                  return -EINVAL;                  return -EINVAL;
1055    
1056          if (sscanf(data, CCS_KEYWORD_USE_PROFILE "%u", &profile) == 1          if (sscanf(data, "use_profile %u\n", &profile) == 1
1057              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
1058                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])
1059                          domain->profile = (u8) profile;                          domain->profile = (u8) profile;
1060                  return 0;                  return 0;
1061          }          }
1062          if (sscanf(data, CCS_KEYWORD_USE_GROUP "%u", &profile) == 1          if (sscanf(data, "use_group %u\n", &profile) == 1
1063              && profile < CCS_MAX_ACL_GROUPS) {              && profile < CCS_MAX_ACL_GROUPS) {
1064                  domain->group = (u8) profile;                  domain->group = (u8) profile;
1065                  return 0;                  return 0;
# Line 1006  static int ccs_write_domain(struct ccs_i Line 1079  static int ccs_write_domain(struct ccs_i
1079   *   *
1080   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1081   * @ptr:  Pointer to "struct ccs_name_union".   * @ptr:  Pointer to "struct ccs_name_union".
1082     *
1083     * Returns nothing.
1084   */   */
1085  static void ccs_print_name_union(struct ccs_io_buffer *head,  static void ccs_print_name_union(struct ccs_io_buffer *head,
1086                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
# Line 1030  static void ccs_print_name_union(struct Line 1105  static void ccs_print_name_union(struct
1105   *   *
1106   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1107   * @ptr:  Pointer to "struct ccs_number_union".   * @ptr:  Pointer to "struct ccs_number_union".
1108     *
1109     * Returns nothing.
1110   */   */
1111  static void ccs_print_number_union(struct ccs_io_buffer *head,  static void ccs_print_number_union(struct ccs_io_buffer *head,
1112                                     const struct ccs_number_union *ptr)                                     const struct ccs_number_union *ptr)
# Line 1195  static bool ccs_print_condition(struct c Line 1272  static bool ccs_print_condition(struct c
1272                  head->r.cond_step++;                  head->r.cond_step++;
1273                  /* fall through */                  /* fall through */
1274          case 3:          case 3:
1275                  if (cond->audit)                  if (cond->grant_log != CCS_GRANTLOG_AUTO)
1276                          ccs_io_printf(head, " audit=%s",                          ccs_io_printf(head, " grant_log=%s",
1277                                        ccs_yesno(cond->audit == 2));                                        ccs_yesno(cond->grant_log ==
1278                                                    CCS_GRANTLOG_YES));
1279                  if (cond->transit) {                  if (cond->transit) {
1280                          ccs_set_string(head, " auto_domain_transitition=\"");                          ccs_set_string(head, " auto_domain_transitition=\"");
1281                          ccs_set_string(head, cond->transit->name);                          ccs_set_string(head, cond->transit->name);
# Line 1225  static u8 ccs_fns(const u8 perm, u8 bit) Line 1303  static u8 ccs_fns(const u8 perm, u8 bit)
1303          return bit;          return bit;
1304  }  }
1305    
1306    /**
1307     * ccs_set_group - Print "acl_group " header keyword.
1308     *
1309     * @head: Pointer to "struct ccs_io_buffer".
1310     *
1311     * Returns nothing.
1312     */
1313  static void ccs_set_group(struct ccs_io_buffer *head)  static void ccs_set_group(struct ccs_io_buffer *head)
1314  {  {
1315          if (head->type == CCS_EXCEPTIONPOLICY)          if (head->type == CCS_EXCEPTIONPOLICY)
# Line 1248  static bool ccs_print_entry(struct ccs_i Line 1333  static bool ccs_print_entry(struct ccs_i
1333                  goto print_cond_part;                  goto print_cond_part;
1334          if (acl->is_deleted)          if (acl->is_deleted)
1335                  return true;                  return true;
1336   next:  next:
1337          bit = head->r.bit;          bit = head->r.bit;
1338          if (!ccs_flush(head))          if (!ccs_flush(head))
1339                  return false;                  return false;
# Line 1301  static bool ccs_print_entry(struct ccs_i Line 1386  static bool ccs_print_entry(struct ccs_i
1386                          goto done;                          goto done;
1387                  ccs_set_group(head);                  ccs_set_group(head);
1388                  ccs_set_string(head, "file ");                  ccs_set_string(head, "file ");
1389                  ccs_set_string(head, ccs_mkdev_keyword[bit]);                  ccs_set_string(head, ccs_mac_keywords[ccs_pnnn2mac[bit]]);
1390                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1391                  ccs_print_number_union(head, &ptr->mode);                  ccs_print_number_union(head, &ptr->mode);
1392                  ccs_print_number_union(head, &ptr->major);                  ccs_print_number_union(head, &ptr->major);
# Line 1314  static bool ccs_print_entry(struct ccs_i Line 1399  static bool ccs_print_entry(struct ccs_i
1399                          goto done;                          goto done;
1400                  ccs_set_group(head);                  ccs_set_group(head);
1401                  ccs_set_string(head, "file ");                  ccs_set_string(head, "file ");
1402                  ccs_set_string(head, ccs_path2_keyword[bit]);                  ccs_set_string(head, ccs_mac_keywords[ccs_pp2mac[bit]]);
1403                  ccs_print_name_union(head, &ptr->name1);                  ccs_print_name_union(head, &ptr->name1);
1404                  ccs_print_name_union(head, &ptr->name2);                  ccs_print_name_union(head, &ptr->name2);
1405          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
# Line 1325  static bool ccs_print_entry(struct ccs_i Line 1410  static bool ccs_print_entry(struct ccs_i
1410                          goto done;                          goto done;
1411                  ccs_set_group(head);                  ccs_set_group(head);
1412                  ccs_set_string(head, "file ");                  ccs_set_string(head, "file ");
1413                  ccs_set_string(head, ccs_path_number_keyword[bit]);                  ccs_set_string(head, ccs_mac_keywords[ccs_pn2mac[bit]]);
1414                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1415                  ccs_print_number_union(head, &ptr->number);                  ccs_print_number_union(head, &ptr->number);
1416          } else if (acl_type == CCS_TYPE_ENV_ACL) {          } else if (acl_type == CCS_TYPE_ENV_ACL) {
# Line 1339  static bool ccs_print_entry(struct ccs_i Line 1424  static bool ccs_print_entry(struct ccs_i
1424                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1425                  ccs_set_group(head);                  ccs_set_group(head);
1426                  ccs_set_string(head, "capability ");                  ccs_set_string(head, "capability ");
1427                  ccs_set_string(head, ccs_cap2keyword(ptr->operation));                  ccs_set_string(head,
1428                                   ccs_mac_keywords[ccs_c2mac[ptr->operation]]);
1429          } else if (acl_type == CCS_TYPE_INET_ACL) {          } else if (acl_type == CCS_TYPE_INET_ACL) {
1430                  struct ccs_inet_acl *ptr =                  struct ccs_inet_acl *ptr =
1431                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
# Line 1406  static bool ccs_print_entry(struct ccs_i Line 1492  static bool ccs_print_entry(struct ccs_i
1492                  head->r.cond_step = 0;                  head->r.cond_step = 0;
1493                  if (!ccs_flush(head))                  if (!ccs_flush(head))
1494                          return false;                          return false;
1495   print_cond_part:  print_cond_part:
1496                  if (!ccs_print_condition(head, acl->cond))                  if (!ccs_print_condition(head, acl->cond))
1497                          return false;                          return false;
1498                  head->r.print_cond_part = false;                  head->r.print_cond_part = false;
# Line 1422  static bool ccs_print_entry(struct ccs_i Line 1508  static bool ccs_print_entry(struct ccs_i
1508          case CCS_TYPE_UNIX_ACL:          case CCS_TYPE_UNIX_ACL:
1509                  goto next;                  goto next;
1510          }          }
1511   done:  done:
1512          head->r.bit = 0;          head->r.bit = 0;
1513          return true;          return true;
1514  }  }
# Line 1475  static void ccs_read_domain(struct ccs_i Line 1561  static void ccs_read_domain(struct ccs_i
1561                          /* Print domainname and flags. */                          /* Print domainname and flags. */
1562                          ccs_set_string(head, domain->domainname->name);                          ccs_set_string(head, domain->domainname->name);
1563                          ccs_set_lf(head);                          ccs_set_lf(head);
1564                          ccs_io_printf(head, CCS_KEYWORD_USE_PROFILE "%u\n",                          ccs_io_printf(head, "use_profile %u\n",
1565                                        domain->profile);                                        domain->profile);
1566                          ccs_io_printf(head, CCS_KEYWORD_USE_GROUP "%u\n",                          ccs_io_printf(head, "use_group %u\n", domain->group);
                                       domain->group);  
1567                          for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)                          for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
1568                                  if (domain->flags[i])                                  if (domain->flags[i])
1569                                          ccs_set_string(head, ccs_dif[i]);                                          ccs_set_string(head, ccs_dif[i]);
# Line 1503  static void ccs_read_domain(struct ccs_i Line 1588  static void ccs_read_domain(struct ccs_i
1588                                  goto done;                                  goto done;
1589                  }                  }
1590          }          }
1591   done:  done:
1592          head->r.eof = true;          head->r.eof = true;
1593  }  }
1594    
# Line 1628  static void ccs_read_pid(struct ccs_io_b Line 1713  static void ccs_read_pid(struct ccs_io_b
1713  #endif  #endif
1714          if (p) {          if (p) {
1715                  domain = ccs_task_domain(p);                  domain = ccs_task_domain(p);
1716                  ccs_flags = p->ccs_flags;                  ccs_flags = ccs_task_flags(p);
1717          }          }
1718          ccs_tasklist_unlock();          ccs_tasklist_unlock();
1719          if (!domain)          if (!domain)
# Line 1645  static void ccs_read_pid(struct ccs_io_b Line 1730  static void ccs_read_pid(struct ccs_io_b
1730          }          }
1731  }  }
1732    
1733  static const char *ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {  /* String table for domain transition control keywords. */
1734          [CCS_TRANSITION_CONTROL_NO_INITIALIZE]  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1735          = CCS_KEYWORD_NO_INITIALIZE_DOMAIN,          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1736          [CCS_TRANSITION_CONTROL_INITIALIZE] = CCS_KEYWORD_INITIALIZE_DOMAIN,          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1737          [CCS_TRANSITION_CONTROL_NO_KEEP] = CCS_KEYWORD_NO_KEEP_DOMAIN,          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",
1738          [CCS_TRANSITION_CONTROL_KEEP] = CCS_KEYWORD_KEEP_DOMAIN          [CCS_TRANSITION_CONTROL_KEEP]          = "keep_domain ",
1739  };  };
1740    
1741  static const char *ccs_group_name[CCS_MAX_GROUP] = {  /* String table for grouping keywords. */
1742          [CCS_PATH_GROUP] = CCS_KEYWORD_PATH_GROUP,  static const char * const ccs_group_name[CCS_MAX_GROUP] = {
1743          [CCS_NUMBER_GROUP] = CCS_KEYWORD_NUMBER_GROUP,          [CCS_PATH_GROUP]    = "path_group ",
1744          [CCS_ADDRESS_GROUP] = CCS_KEYWORD_ADDRESS_GROUP          [CCS_NUMBER_GROUP]  = "number_group ",
1745            [CCS_ADDRESS_GROUP] = "address_group ",
1746  };  };
1747    
1748  /**  /**
# Line 1669  static const char *ccs_group_name[CCS_MA Line 1755  static const char *ccs_group_name[CCS_MA
1755  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1756  {  {
1757          char *data = head->write_buf;          char *data = head->write_buf;
1758          const bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);          const bool is_delete = ccs_str_starts(&data, "delete ");
1759          u8 i;          u8 i;
1760          static const struct {          static const struct {
1761                  const char *keyword;                  const char *keyword;
1762                  int (*write) (char *, const bool);                  int (*write) (char *, const bool);
1763          } ccs_callback[3] = {          } ccs_callback[2] = {
1764                  { CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator },                  { "aggregator ",    ccs_write_aggregator },
1765                  { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },                  { "deny_autobind ", ccs_write_reserved_port },
                 { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }  
1766          };          };
1767          for (i = 0; i < 3; i++)          for (i = 0; i < 2; i++)
1768                  if (ccs_str_starts(&data, ccs_callback[i].keyword))                  if (ccs_str_starts(&data, ccs_callback[i].keyword))
1769                          return ccs_callback[i].write(data, is_delete);                          return ccs_callback[i].write(data, is_delete);
1770          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
# Line 1734  static bool ccs_read_group(struct ccs_io Line 1819  static bool ccs_read_group(struct ccs_io
1819                                                  head)->member_name->name);                                                  head)->member_name->name);
1820                          } else if (idx == CCS_NUMBER_GROUP) {                          } else if (idx == CCS_NUMBER_GROUP) {
1821                                  ccs_print_number_union(head, &container_of                                  ccs_print_number_union(head, &container_of
1822                                                         (ptr, struct ccs_number_group,                                                 (ptr, struct ccs_number_group,
1823                                                          head)->number);                                                  head)->number);
1824                          } else if (idx == CCS_ADDRESS_GROUP) {                          } else if (idx == CCS_ADDRESS_GROUP) {
1825                                  char buffer[128];                                  char buffer[128];
1826                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
# Line 1796  static bool ccs_read_policy(struct ccs_i Line 1881  static bool ccs_read_policy(struct ccs_i
1881                          {                          {
1882                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
1883                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
1884                                  ccs_set_string(head, CCS_KEYWORD_AGGREGATOR);                                  ccs_set_string(head, "aggregator ");
1885                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
1886                                  ccs_set_space(head);                                  ccs_set_space(head);
1887                                  ccs_set_string(head,                                  ccs_set_string(head,
1888                                                 ptr->aggregated_name->name);                                                 ptr->aggregated_name->name);
1889                          }                          }
1890                          break;                          break;
                 case CCS_ID_PATTERN:  
                         {  
                                 struct ccs_pattern *ptr =  
                                         container_of(acl, typeof(*ptr), head);  
                                 ccs_set_string(head, CCS_KEYWORD_FILE_PATTERN);  
                                 ccs_set_string(head, ptr->pattern->name);  
                         }  
                         break;  
1891                  case CCS_ID_RESERVEDPORT:                  case CCS_ID_RESERVEDPORT:
1892                          {                          {
1893                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
1894                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
1895                                  const u16 min_port = ptr->min_port;                                  const u16 min_port = ptr->min_port;
1896                                  const u16 max_port = ptr->max_port;                                  const u16 max_port = ptr->max_port;
1897                                  ccs_set_string(head,                                  ccs_set_string(head, "deny_autobind ");
                                                CCS_KEYWORD_DENY_AUTOBIND);  
1898                                  ccs_io_printf(head, "%u", min_port);                                  ccs_io_printf(head, "%u", min_port);
1899                                  if (min_port != max_port)                                  if (min_port != max_port)
1900                                          ccs_io_printf(head, "-%u", max_port);                                          ccs_io_printf(head, "-%u", max_port);
# Line 1867  static void ccs_read_exception(struct cc Line 1943  static void ccs_read_exception(struct cc
1943          head->r.eof = true;          head->r.eof = true;
1944  }  }
1945    
1946  /* Wait queue for ccs_query_list. */  /* Wait queue for kernel -> userspace notification. */
1947  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1948    /* Wait queue for userspace -> kernel notification. */
1949    static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
1950    
1951  /* Lock for manipulating ccs_query_list. */  /* Lock for manipulating ccs_query_list. */
1952  static DEFINE_SPINLOCK(ccs_query_list_lock);  static DEFINE_SPINLOCK(ccs_query_list_lock);
# Line 1881  struct ccs_query { Line 1959  struct ccs_query {
1959          unsigned int serial;          unsigned int serial;
1960          int timer;          int timer;
1961          int answer;          int answer;
1962            u8 retry;
1963  };  };
1964    
1965  /* The list for "struct ccs_query". */  /* The list for "struct ccs_query". */
# Line 1889  static LIST_HEAD(ccs_query_list); Line 1968  static LIST_HEAD(ccs_query_list);
1968  /* Number of "struct file" referring /proc/ccs/query interface. */  /* Number of "struct file" referring /proc/ccs/query interface. */
1969  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1970    
1971  static void ccs_truncate(char *str)  /**
1972     * ccs_truncate - Truncate a line.
1973     *
1974     * @str: String to truncate.
1975     *
1976     * Returns length of truncated @str.
1977     */
1978    static int ccs_truncate(char *str)
1979  {  {
1980          while (* (unsigned char *) str > (unsigned char) ' ')          char *start = str;
1981            while (*(unsigned char *) str > (unsigned char) ' ')
1982                  str++;                  str++;
1983          *str = '\0';          *str = '\0';
1984            return strlen(start) + 1;
1985    }
1986    
1987    /**
1988     * ccs_add_entry - Add an ACL to current thread's domain. Used by learning mode.
1989     *
1990     * @header: Lines containing ACL.
1991     *
1992     * Returns nothing.
1993     */
1994    static void ccs_add_entry(char *header)
1995    {
1996            char *buffer;
1997            char *realpath = NULL;
1998            char *argv0 = NULL;
1999            char *symlink = NULL;
2000            char *handler;
2001            char *cp = strchr(header, '\n');
2002            int len;
2003            if (!cp)
2004                    return;
2005            cp = strchr(cp + 1, '\n');
2006            if (!cp)
2007                    return;
2008            *cp++ = '\0';
2009            len = strlen(cp) + 1;
2010            /* strstr() will return NULL if ordering is wrong. */
2011            if (*cp == 'f') {
2012                    argv0 = strstr(header, " argv[]={ \"");
2013                    if (argv0) {
2014                            argv0 += 10;
2015                            len += ccs_truncate(argv0) + 14;
2016                    }
2017                    realpath = strstr(header, " exec={ realpath=\"");
2018                    if (realpath) {
2019                            realpath += 8;
2020                            len += ccs_truncate(realpath) + 6;
2021                    }
2022                    symlink = strstr(header, " symlink.target=\"");
2023                    if (symlink)
2024                            len += ccs_truncate(symlink + 1) + 1;
2025            }
2026            handler = strstr(header, "type=execute_handler");
2027            if (handler)
2028                    len += ccs_truncate(handler) + 6;
2029            buffer = kmalloc(len, CCS_GFP_FLAGS);
2030            if (!buffer)
2031                    return;
2032            snprintf(buffer, len - 1, "%s", cp);
2033            if (handler)
2034                    ccs_addprintf(buffer, len, " task.%s", handler);
2035            if (realpath)
2036                    ccs_addprintf(buffer, len, " exec.%s", realpath);
2037            if (argv0)
2038                    ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
2039            if (symlink)
2040                    ccs_addprintf(buffer, len, "%s", symlink);
2041            ccs_normalize_line(buffer);
2042            if (!ccs_write_domain2(buffer, ccs_current_domain(), false))
2043                    ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2044            kfree(buffer);
2045  }  }
2046    
2047  /**  /**
# Line 1910  static void ccs_truncate(char *str) Line 2058  static void ccs_truncate(char *str)
2058  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
2059  {  {
2060          va_list args;          va_list args;
2061          int error = -EPERM;          int error;
         int pos;  
2062          int len;          int len;
2063          static unsigned int ccs_serial;          static unsigned int ccs_serial;
2064          struct ccs_query *entry = NULL;          struct ccs_query entry = { };
2065          bool quota_exceeded = false;          bool quota_exceeded = false;
         char *header;  
         struct ccs_domain_info * const domain = ccs_current_domain();  
2066          va_start(args, fmt);          va_start(args, fmt);
2067          len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 80;          len = vsnprintf((char *) &len, 1, fmt, args) + 1;
2068          va_end(args);          va_end(args);
2069          if (r->mode == CCS_CONFIG_LEARNING) {          /* Write /proc/ccs/grant_log or /proc/ccs/reject_log . */
2070                  char *buffer;          va_start(args, fmt);
2071                  char *realpath = NULL;          ccs_write_log2(r, len, fmt, args);
2072                  char *argv0 = NULL;          va_end(args);
2073                  char *symlink = NULL;          /* Nothing more to do if granted. */
2074                  char *handler = NULL;          if (r->granted)
                 if (!ccs_domain_quota_ok(r))  
                         return 0;  
                 header = ccs_init_log(&len, r);  
                 if (!header)  
                         return 0;  
                 /* strstr() will return NULL if ordering is wrong. */  
                 if (r->param_type == CCS_TYPE_PATH_ACL &&  
                     r->param.path.operation == CCS_TYPE_EXECUTE) {  
                         if (ccs_preference.learning_exec_argv0) {  
                                 argv0 = strstr(header, " argv[]={ \"");  
                                 if (argv0) {  
                                         argv0 += 10;  
                                         ccs_truncate(argv0);  
                                 }  
                         }  
                         if (ccs_preference.learning_exec_realpath) {  
                                 realpath = strstr(header,  
                                                   " exec={ realpath=\"");  
                                 if (realpath) {  
                                         realpath += 8;  
                                         ccs_truncate(realpath);  
                                 }  
                         }  
                 } else if (r->param_type == CCS_TYPE_PATH_ACL &&  
                            r->param.path.operation == CCS_TYPE_SYMLINK &&  
                            ccs_preference.learning_symlink_target) {  
                         symlink = strstr(header, " symlink.target=\"");  
                         if (symlink)  
                                 ccs_truncate(symlink + 1);  
                 }  
                 handler = strstr(header, "type=execute_handler");  
                 if (handler)  
                         ccs_truncate(handler);  
                 buffer = kmalloc(len, CCS_GFP_FLAGS);  
                 if (buffer) {  
                         va_start(args, fmt);  
                         vsnprintf(buffer, len - 1, fmt, args);  
                         va_end(args);  
                         if (handler || realpath || argv0 || symlink) {  
                                 if (handler)  
                                         ccs_addprintf(buffer, len, " task.%s",  
                                                       handler);  
                                 if (realpath)  
                                         ccs_addprintf(buffer, len, " exec.%s",  
                                                       realpath);  
                                 if (argv0)  
                                         ccs_addprintf(buffer, len,  
                                                       " exec.argv[0]=%s",  
                                                       argv0);  
                                 if (symlink)  
                                         ccs_addprintf(buffer, len, "%s",  
                                                       symlink);  
                         }  
                         ccs_normalize_line(buffer);  
                         ccs_write_domain2(buffer, domain, false);  
                         kfree(buffer);  
                 }  
                 kfree(header);  
                 return 0;  
         }  
         if (r->mode != CCS_CONFIG_ENFORCING)  
2075                  return 0;                  return 0;
2076          if (!atomic_read(&ccs_query_observers)) {          if (r->mode)
2077                    ccs_update_stat(r->mode);
2078            switch (r->mode) {
2079                  int i;                  int i;
2080                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  struct ccs_profile *p;
2081                          return -EPERM;          case CCS_CONFIG_ENFORCING:
2082                  for (i = 0; i < ccs_preference.enforcing_penalty; i++) {                  error = -EPERM;
2083                    if (atomic_read(&ccs_query_observers))
2084                            break;
2085                    if (ccs_current_flags() & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
2086                            goto out;
2087                    p = ccs_profile(r->profile);
2088                    /* Check enforcing_penalty parameter. */
2089                    for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
2090                          set_current_state(TASK_INTERRUPTIBLE);                          set_current_state(TASK_INTERRUPTIBLE);
2091                          schedule_timeout(HZ / 10);                          schedule_timeout(HZ / 10);
2092                  }                  }
                 return -EPERM;  
         }  
         header = ccs_init_log(&len, r);  
         if (!header)  
2093                  goto out;                  goto out;
2094          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);          case CCS_CONFIG_LEARNING:
2095          if (!entry)                  error = 0;
2096                    /* Check mac_learning_entry parameter. */
2097                    if (ccs_domain_quota_ok(r))
2098                            break;
2099                    /* fall through */
2100            default:
2101                    return 0;
2102            }
2103            /* Get message. */
2104            va_start(args, fmt);
2105            entry.query = ccs_init_log(r, len, fmt, args);
2106            va_end(args);
2107            if (!entry.query)
2108                  goto out;                  goto out;
2109          len = ccs_round2(len);          entry.query_len = strlen(entry.query) + 1;
2110          entry->query = kzalloc(len, CCS_GFP_FLAGS);          if (!error) {
2111          if (!entry->query)                  ccs_add_entry(entry.query);
2112                  goto out;                  goto out;
2113            }
2114            len = ccs_round2(entry.query_len);
2115          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2116          if (ccs_quota_for_query && ccs_query_memory_size + len +          if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
2117              sizeof(*entry) >= ccs_quota_for_query) {              ccs_memory_used[CCS_MEMORY_QUERY] + len
2118                >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
2119                  quota_exceeded = true;                  quota_exceeded = true;
2120          } else {          } else {
2121                  ccs_query_memory_size += len + sizeof(*entry);                  entry.serial = ccs_serial++;
2122                  entry->serial = ccs_serial++;                  entry.retry = r->retry;
2123                    ccs_memory_used[CCS_MEMORY_QUERY] += len;
2124                    list_add_tail(&entry.list, &ccs_query_list);
2125          }          }
2126          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2127          if (quota_exceeded)          if (quota_exceeded)
2128                  goto out;                  goto out;
         pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s",  
                        entry->serial, r->retry, header);  
         kfree(header);  
         header = NULL;  
         va_start(args, fmt);  
         vsnprintf(entry->query + pos, len - 1 - pos, fmt, args);  
         entry->query_len = strlen(entry->query) + 1;  
         va_end(args);  
         spin_lock(&ccs_query_list_lock);  
         list_add_tail(&entry->list, &ccs_query_list);  
         spin_unlock(&ccs_query_list_lock);  
2129          /* Give 10 seconds for supervisor's opinion. */          /* Give 10 seconds for supervisor's opinion. */
2130          for (entry->timer = 0;          while (entry.timer < 10) {
2131               atomic_read(&ccs_query_observers) && entry->timer < 100;                  wake_up_all(&ccs_query_wait);
2132               entry->timer++) {                  if (wait_event_interruptible_timeout
2133                  wake_up(&ccs_query_wait);                      (ccs_answer_wait, entry.answer ||
2134                  set_current_state(TASK_INTERRUPTIBLE);                       !atomic_read(&ccs_query_observers), HZ))
                 schedule_timeout(HZ / 10);  
                 if (entry->answer)  
2135                          break;                          break;
2136                    else
2137                            entry.timer++;
2138          }          }
2139          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2140          list_del(&entry->list);          list_del(&entry.list);
2141          ccs_query_memory_size -= len + sizeof(*entry);          ccs_memory_used[CCS_MEMORY_QUERY] -= len;
2142          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2143          switch (entry->answer) {          switch (entry.answer) {
2144          case 3: /* Asked to retry by administrator. */          case 3: /* Asked to retry by administrator. */
2145                  error = CCS_RETRY_REQUEST;                  error = CCS_RETRY_REQUEST;
2146                  r->retry++;                  r->retry++;
# Line 2054  int ccs_supervisor(struct ccs_request_in Line 2149  int ccs_supervisor(struct ccs_request_in
2149                  /* Granted by administrator. */                  /* Granted by administrator. */
2150                  error = 0;                  error = 0;
2151                  break;                  break;
         case 0:  
                 /* Timed out. */  
                 break;  
2152          default:          default:
2153                  /* Rejected by administrator. */                  /* Timed out or rejected by administrator. */
2154                  break;                  break;
2155          }          }
2156   out:  out:
2157          if (entry)          kfree(entry.query);
                 kfree(entry->query);  
         kfree(entry);  
         kfree(header);  
2158          return error;          return error;
2159  }  }
2160    
# Line 2108  static int ccs_poll_query(struct file *f Line 2197  static int ccs_poll_query(struct file *f
2197   * ccs_read_query - Read access requests which violated policy in enforcing mode.   * ccs_read_query - Read access requests which violated policy in enforcing mode.
2198   *   *
2199   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2200     *
2201     * Returns nothing.
2202   */   */
2203  static void ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2204  {  {
# Line 2136  static void ccs_read_query(struct ccs_io Line 2227  static void ccs_read_query(struct ccs_io
2227                  head->r.query_index = 0;                  head->r.query_index = 0;
2228                  return;                  return;
2229          }          }
2230          buf = kzalloc(len, CCS_GFP_FLAGS);          buf = kzalloc(len + 32, CCS_GFP_FLAGS);
2231          if (!buf)          if (!buf)
2232                  return;                  return;
2233          pos = 0;          pos = 0;
# Line 2152  static void ccs_read_query(struct ccs_io Line 2243  static void ccs_read_query(struct ccs_io
2243                   * can change, but I don't care.                   * can change, but I don't care.
2244                   */                   */
2245                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2246                          memmove(buf, ptr->query, len);                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,
2247                                     ptr->retry, ptr->query);
2248                  break;                  break;
2249          }          }
2250          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2196  static int ccs_write_answer(struct ccs_i Line 2288  static int ccs_write_answer(struct ccs_i
2288                  break;                  break;
2289          }          }
2290          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2291            wake_up_all(&ccs_answer_wait);
2292          return 0;          return 0;
2293  }  }
2294    
# Line 2203  static int ccs_write_answer(struct ccs_i Line 2296  static int ccs_write_answer(struct ccs_i
2296   * ccs_read_version: Get version.   * ccs_read_version: Get version.
2297   *   *
2298   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2299     *
2300     * Returns nothing.
2301   */   */
2302  static void ccs_read_version(struct ccs_io_buffer *head)  static void ccs_read_version(struct ccs_io_buffer *head)
2303  {  {
# Line 2212  static void ccs_read_version(struct ccs_ Line 2307  static void ccs_read_version(struct ccs_
2307          head->r.eof = true;          head->r.eof = true;
2308  }  }
2309    
2310    /* String table for /proc/ccs/meminfo interface. */
2311    static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
2312            [CCS_STAT_POLICY_UPDATES]    = "update:",
2313            [CCS_STAT_POLICY_LEARNING]   = "violation in learning mode:",
2314            [CCS_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:",
2315            [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
2316    };
2317    
2318    /* String table for /proc/ccs/meminfo interface. */
2319    static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2320            [CCS_MEMORY_POLICY] = "policy:",
2321            [CCS_MEMORY_AUDIT]  = "audit log:",
2322            [CCS_MEMORY_QUERY]  = "query message:",
2323    };
2324    
2325    /* Timestamp counter for last updated. */
2326    static unsigned int ccs_stat_updated[CCS_MAX_POLICY_STAT];
2327    /* Counter for number of updates. */
2328    static unsigned int ccs_stat_modified[CCS_MAX_POLICY_STAT];
2329    
2330  /**  /**
2331   * ccs_read_self_domain - Get the current process's domainname.   * ccs_update_stat - Update statistic counters.
2332     *
2333     * @index: Index for policy type.
2334     *
2335     * Returns nothing.
2336     */
2337    void ccs_update_stat(const u8 index)
2338    {
2339            struct timeval tv;
2340            do_gettimeofday(&tv);
2341            /*
2342             * I don't use atomic operations because race condition is not fatal.
2343             */
2344            ccs_stat_updated[index]++;
2345            ccs_stat_modified[index] = tv.tv_sec;
2346    }
2347    
2348    /**
2349     * ccs_read_stat - Read statistic data.
2350   *   *
2351   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2352     *
2353     * Returns nothing.
2354   */   */
2355  static void ccs_read_self_domain(struct ccs_io_buffer *head)  static void ccs_read_stat(struct ccs_io_buffer *head)
2356  {  {
2357            u8 i;
2358            unsigned int total = 0;
2359          if (head->r.eof)          if (head->r.eof)
2360                  return;                  return;
2361          /*          for (i = 0; i < CCS_MAX_POLICY_STAT; i++) {
2362           * ccs_current_domain()->domainname != NULL because every process                  ccs_io_printf(head, "Policy %-30s %10u", ccs_policy_headers[i],
2363           * belongs to a domain and the domain's name cannot be NULL.                                ccs_stat_updated[i]);
2364           */                  if (ccs_stat_modified[i]) {
2365          ccs_io_printf(head, "%s", ccs_current_domain()->domainname->name);                          struct ccs_time stamp;
2366                            ccs_convert_time(ccs_stat_modified[i], &stamp);
2367                            ccs_io_printf(head, " (Last: %04u/%02u/%02u "
2368                                          "%02u:%02u:%02u)",
2369                                          stamp.year, stamp.month, stamp.day,
2370                                          stamp.hour, stamp.min, stamp.sec);
2371                    }
2372                    ccs_set_lf(head);
2373            }
2374            for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
2375                    unsigned int used = ccs_memory_used[i];
2376                    total += used;
2377                    ccs_io_printf(head, "Memory used by %-22s %10u",
2378                                  ccs_memory_headers[i], used);
2379                    used = ccs_memory_quota[i];
2380                    if (used)
2381                            ccs_io_printf(head, " (Quota: %10u)", used);
2382                    ccs_set_lf(head);
2383            }
2384            ccs_io_printf(head, "Total memory used:                    %10u\n",
2385                          total);
2386            head->r.eof = true;
2387    }
2388    
2389    /**
2390     * ccs_write_stat - Set memory quota.
2391     *
2392     * @head: Pointer to "struct ccs_io_buffer".
2393     *
2394     * Returns 0.
2395     */
2396    static int ccs_write_stat(struct ccs_io_buffer *head)
2397    {
2398            char *data = head->write_buf;
2399            u8 i;
2400            if (ccs_str_starts(&data, "Memory used by "))
2401                    for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2402                            if (ccs_str_starts(&data, ccs_memory_headers[i]))
2403                                    sscanf(data, "%u", &ccs_memory_quota[i]);
2404            return 0;
2405    }
2406    
2407    /* String table for /proc/ccs/meminfo interface. */
2408    static const char * const ccs_old_memory_header[CCS_MAX_MEMORY_STAT] = {
2409            [CCS_MEMORY_POLICY] = "Policy:",
2410            [CCS_MEMORY_AUDIT]  = "Audit logs:",
2411            [CCS_MEMORY_QUERY]  = "Query lists:",
2412    };
2413    
2414    /**
2415     * ccs_read_memory_counter - Read memory usage.
2416     *
2417     * @head: Pointer to "struct ccs_io_buffer".
2418     *
2419     * Returns nothing.
2420     */
2421    static void ccs_read_memory_counter(struct ccs_io_buffer *head)
2422    {
2423            unsigned int total = 0;
2424            int i;
2425            if (head->r.eof)
2426                    return;
2427            for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {
2428                    unsigned int used = ccs_memory_used[i];
2429                    total += used;
2430                    ccs_io_printf(head, "%-12s %10u", ccs_old_memory_header[i],
2431                                  used);
2432                    if (ccs_memory_quota[i])
2433                            ccs_io_printf(head, "   (Quota: %10u)",
2434                                          ccs_memory_quota[i]);
2435                    ccs_io_printf(head, "\n");
2436            }
2437            ccs_io_printf(head, "%-12s %10u\n", "Total:", total);
2438          head->r.eof = true;          head->r.eof = true;
2439  }  }
2440    
2441  /**  /**
2442     * ccs_write_memory_quota - Set memory quota.
2443     *
2444     * @head: Pointer to "struct ccs_io_buffer".
2445     *
2446     * Returns 0.
2447     */
2448    static int ccs_write_memory_quota(struct ccs_io_buffer *head)
2449    {
2450            char *data = head->write_buf;
2451            u8 i;
2452            for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2453                    if (ccs_str_starts(&data, ccs_old_memory_header[i]))
2454                            sscanf(data, "%u", &ccs_memory_quota[i]);
2455            return 0;
2456    }
2457    
2458    /**
2459   * ccs_open_control - open() for /proc/ccs/ interface.   * ccs_open_control - open() for /proc/ccs/ interface.
2460   *   *
2461   * @type: Type of interface.   * @type: Type of interface.
# Line 2253  int ccs_open_control(const u8 type, stru Line 2479  int ccs_open_control(const u8 type, stru
2479                  head->write = ccs_write_exception;                  head->write = ccs_write_exception;
2480                  head->read = ccs_read_exception;                  head->read = ccs_read_exception;
2481                  break;                  break;
 #ifdef CONFIG_CCSECURITY_AUDIT  
2482          case CCS_GRANTLOG: /* /proc/ccs/grant_log */          case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2483          case CCS_REJECTLOG: /* /proc/ccs/reject_log */          case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2484                  head->poll = ccs_poll_log;                  head->poll = ccs_poll_log;
2485                  head->read = ccs_read_log;                  head->read = ccs_read_log;
2486                  break;                  break;
 #endif  
         case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */  
                 head->read = ccs_read_self_domain;  
                 break;  
2487          case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */          case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
2488                  head->write = ccs_write_domain_profile;                  head->write = ccs_write_domain_profile;
2489                  head->read = ccs_read_domain_profile;                  head->read = ccs_read_domain_profile;
2490                  break;                  break;
2491          case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */          case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
2492                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
2493                  if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
2494                          kfree(head);                          kfree(head);
2495                          return -EPERM;                          return -EPERM;
2496                  }                  }
# Line 2282  int ccs_open_control(const u8 type, stru Line 2503  int ccs_open_control(const u8 type, stru
2503                  head->read = ccs_read_version;                  head->read = ccs_read_version;
2504                  head->readbuf_size = 128;                  head->readbuf_size = 128;
2505                  break;                  break;
2506            case CCS_STAT: /* /proc/ccs/stat */
2507                    head->write = ccs_write_stat;
2508                    head->read = ccs_read_stat;
2509                    head->readbuf_size = 1024;
2510                    break;
2511          case CCS_MEMINFO: /* /proc/ccs/meminfo */          case CCS_MEMINFO: /* /proc/ccs/meminfo */
2512                  head->write = ccs_write_memory_quota;                  head->write = ccs_write_memory_quota;
2513                  head->read = ccs_read_memory_counter;                  head->read = ccs_read_memory_counter;
# Line 2333  int ccs_open_control(const u8 type, stru Line 2559  int ccs_open_control(const u8 type, stru
2559                          return -ENOMEM;                          return -ENOMEM;
2560                  }                  }
2561          }          }
         if (type != CCS_QUERY &&  
             type != CCS_GRANTLOG && type != CCS_REJECTLOG)  
                 head->reader_idx = ccs_lock();  
         file->private_data = head;  
         /*  
          * Call the handler now if the file is /proc/ccs/self_domain  
          * so that the user can use "cat < /proc/ccs/self_domain" to  
          * know the current process's domainname.  
          */  
         if (type == CCS_SELFDOMAIN)  
                 ccs_read_control(file, NULL, 0);  
2562          /*          /*
2563           * If the file is /proc/ccs/query , increment the observer counter.           * If the file is /proc/ccs/query , increment the observer counter.
2564           * The obserber counter is used by ccs_supervisor() to see if           * The obserber counter is used by ccs_supervisor() to see if
2565           * there is some process monitoring /proc/ccs/query.           * there is some process monitoring /proc/ccs/query.
2566           */           */
2567          else if (type == CCS_QUERY)          if (type == CCS_QUERY)
2568                  atomic_inc(&ccs_query_observers);                  atomic_inc(&ccs_query_observers);
2569            else if (type != CCS_GRANTLOG && type != CCS_REJECTLOG &&
2570                     type != CCS_VERSION && type != CCS_MEMINFO &&
2571                     type != CCS_STAT)
2572                    head->reader_idx = ccs_lock();
2573            file->private_data = head;
2574          return 0;          return 0;
2575  }  }
2576    
# Line 2360  int ccs_open_control(const u8 type, stru Line 2580  int ccs_open_control(const u8 type, stru
2580   * @file: Pointer to "struct file".   * @file: Pointer to "struct file".
2581   * @wait: Pointer to "poll_table".   * @wait: Pointer to "poll_table".
2582   *   *
2583     * Returns return value of poll().
2584     *
2585   * Waits for read readiness.   * Waits for read readiness.
2586   * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and   * /proc/ccs/query is handled by /usr/sbin/ccs-queryd and
2587   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by   * /proc/ccs/grant_log and /proc/ccs/reject_log are handled by
# Line 2466  int ccs_write_control(struct file *file, Line 2688  int ccs_write_control(struct file *file,
2688                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2689                  head->w.avail = 0;                  head->w.avail = 0;
2690                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2691                  head->write(head);                  if (head->write(head))
2692                            continue;
2693                    switch (head->type) {
2694                    case CCS_DOMAINPOLICY:
2695                    case CCS_EXCEPTIONPOLICY:
2696                    case CCS_DOMAIN_STATUS:
2697                    case CCS_MEMINFO:
2698                    case CCS_PROFILE:
2699                    case CCS_MANAGER:
2700                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2701                    }
2702          }          }
2703          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2704          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2488  int ccs_close_control(struct file *file) Line 2720  int ccs_close_control(struct file *file)
2720          /*          /*
2721           * If the file is /proc/ccs/query , decrement the observer counter.           * If the file is /proc/ccs/query , decrement the observer counter.
2722           */           */
2723          if (type == CCS_QUERY)          if (type == CCS_QUERY) {
2724                  atomic_dec(&ccs_query_observers);                  if (atomic_dec_and_test(&ccs_query_observers))
2725          if (type != CCS_QUERY &&                          wake_up_all(&ccs_answer_wait);
2726              type != CCS_GRANTLOG && type != CCS_REJECTLOG)          } else if (type != CCS_GRANTLOG && type != CCS_REJECTLOG &&
2727                       type != CCS_VERSION && type != CCS_MEMINFO &&
2728                       type != CCS_STAT)
2729                  ccs_unlock(head->reader_idx);                  ccs_unlock(head->reader_idx);
2730          /* Release memory used for policy I/O. */          /* Release memory used for policy I/O. */
2731          kfree(head->read_buf);          kfree(head->read_buf);
# Line 2506  int ccs_close_control(struct file *file) Line 2740  int ccs_close_control(struct file *file)
2740          return 0;          return 0;
2741  }  }
2742    
2743    /**
2744     * ccs_policy_io_init - Register hooks for policy I/O.
2745     *
2746     * Returns nothing.
2747     */
2748  void __init ccs_policy_io_init(void)  void __init ccs_policy_io_init(void)
2749  {  {
2750          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;

Legend:
Removed from v.3961  
changed lines
  Added in v.4080

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