2 * security/tomoyo/audit.c
4 * Copyright (C) 2005-2011 NTT DATA CORPORATION
8 #include <linux/slab.h>
11 * tomoyo_print_bprm - Print "struct linux_binprm" for auditing.
13 * @bprm: Pointer to "struct linux_binprm".
14 * @dump: Pointer to "struct tomoyo_page_dump".
16 * Returns the contents of @bprm on success, NULL otherwise.
18 * This function uses kzalloc(), so caller must kfree() if this function
21 static char *tomoyo_print_bprm(struct linux_binprm
*bprm
,
22 struct tomoyo_page_dump
*dump
)
24 static const int tomoyo_buffer_len
= 4096 * 2;
25 char *buffer
= kzalloc(tomoyo_buffer_len
, GFP_NOFS
);
29 unsigned long pos
= bprm
->p
;
30 int offset
= pos
% PAGE_SIZE
;
31 int argv_count
= bprm
->argc
;
32 int envp_count
= bprm
->envc
;
33 bool truncated
= false;
36 len
= snprintf(buffer
, tomoyo_buffer_len
- 1, "argv[]={ ");
39 memmove(cp
, "} envp[]={ ", 11);
43 while (argv_count
|| envp_count
) {
44 if (!tomoyo_dump_page(bprm
, pos
, dump
))
46 pos
+= PAGE_SIZE
- offset
;
48 while (offset
< PAGE_SIZE
) {
49 const char *kaddr
= dump
->data
;
50 const unsigned char c
= kaddr
[offset
++];
53 if (cp
>= buffer
+ tomoyo_buffer_len
- 32) {
54 /* Reserve some room for "..." string. */
56 } else if (c
== '\\') {
59 } else if (c
> ' ' && c
< 127) {
67 *cp
++ = (c
>> 6) + '0';
68 *cp
++ = ((c
>> 3) & 7) + '0';
69 *cp
++ = (c
& 7) + '0';
74 if (--argv_count
== 0) {
77 memmove(cp
, "... ", 4);
80 memmove(cp
, "} envp[]={ ", 11);
85 } else if (envp_count
) {
86 if (--envp_count
== 0) {
89 memmove(cp
, "... ", 4);
94 if (!argv_count
&& !envp_count
)
103 snprintf(buffer
, tomoyo_buffer_len
- 1,
104 "argv[]={ ... } envp[]= { ... }");
109 * tomoyo_filetype - Get string representation of file type.
111 * @mode: Mode value for stat().
113 * Returns file type string.
115 static inline const char *tomoyo_filetype(const umode_t mode
)
117 switch (mode
& S_IFMT
) {
120 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_FILE
];
122 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_DIRECTORY
];
124 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_SYMLINK
];
126 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_FIFO
];
128 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_SOCKET
];
130 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_BLOCK_DEV
];
132 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_CHAR_DEV
];
134 return "unknown"; /* This should not happen. */
138 * tomoyo_print_header - Get header line of audit log.
140 * @r: Pointer to "struct tomoyo_request_info".
142 * Returns string representation.
144 * This function uses kmalloc(), so caller must kfree() if this function
145 * didn't return NULL.
147 static char *tomoyo_print_header(struct tomoyo_request_info
*r
)
149 struct tomoyo_time stamp
;
150 const pid_t gpid
= task_pid_nr(current
);
151 struct tomoyo_obj_info
*obj
= r
->obj
;
152 static const int tomoyo_buffer_len
= 4096;
153 char *buffer
= kmalloc(tomoyo_buffer_len
, GFP_NOFS
);
160 do_gettimeofday(&tv
);
161 tomoyo_convert_time(tv
.tv_sec
, &stamp
);
163 pos
= snprintf(buffer
, tomoyo_buffer_len
- 1,
164 "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
165 "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
166 "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
167 "fsuid=%u fsgid=%u }", stamp
.year
, stamp
.month
,
168 stamp
.day
, stamp
.hour
, stamp
.min
, stamp
.sec
, r
->profile
,
169 tomoyo_mode
[r
->mode
], tomoyo_yesno(r
->granted
), gpid
,
170 tomoyo_sys_getpid(), tomoyo_sys_getppid(),
171 current_uid(), current_gid(), current_euid(),
172 current_egid(), current_suid(), current_sgid(),
173 current_fsuid(), current_fsgid());
176 if (!obj
->validate_done
) {
177 tomoyo_get_attributes(obj
);
178 obj
->validate_done
= true;
180 for (i
= 0; i
< TOMOYO_MAX_PATH_STAT
; i
++) {
181 struct tomoyo_mini_stat
*stat
;
184 if (!obj
->stat_valid
[i
])
186 stat
= &obj
->stat
[i
];
190 pos
+= snprintf(buffer
+ pos
,
191 tomoyo_buffer_len
- 1 - pos
,
192 " path%u.parent={ uid=%u gid=%u "
193 "ino=%lu perm=0%o }", (i
>> 1) + 1,
194 stat
->uid
, stat
->gid
, (unsigned long)
195 stat
->ino
, stat
->mode
& S_IALLUGO
);
198 pos
+= snprintf(buffer
+ pos
, tomoyo_buffer_len
- 1 - pos
,
199 " path%u={ uid=%u gid=%u ino=%lu major=%u"
200 " minor=%u perm=0%o type=%s", (i
>> 1) + 1,
201 stat
->uid
, stat
->gid
, (unsigned long)
202 stat
->ino
, MAJOR(dev
), MINOR(dev
),
203 mode
& S_IALLUGO
, tomoyo_filetype(mode
));
204 if (S_ISCHR(mode
) || S_ISBLK(mode
)) {
206 pos
+= snprintf(buffer
+ pos
,
207 tomoyo_buffer_len
- 1 - pos
,
208 " dev_major=%u dev_minor=%u",
209 MAJOR(dev
), MINOR(dev
));
211 pos
+= snprintf(buffer
+ pos
, tomoyo_buffer_len
- 1 - pos
,
215 if (pos
< tomoyo_buffer_len
- 1)
222 * tomoyo_init_log - Allocate buffer for audit logs.
224 * @r: Pointer to "struct tomoyo_request_info".
225 * @len: Buffer size needed for @fmt and @args.
226 * @fmt: The printf()'s format string.
227 * @args: va_list structure for @fmt.
229 * Returns pointer to allocated memory.
231 * This function uses kzalloc(), so caller must kfree() if this function
232 * didn't return NULL.
234 char *tomoyo_init_log(struct tomoyo_request_info
*r
, int len
, const char *fmt
,
238 char *bprm_info
= NULL
;
239 const char *header
= NULL
;
240 char *realpath
= NULL
;
241 const char *symlink
= NULL
;
243 const char *domainname
= r
->domain
->domainname
->name
;
244 header
= tomoyo_print_header(r
);
247 /* +10 is for '\n' etc. and '\0'. */
248 len
+= strlen(domainname
) + strlen(header
) + 10;
250 struct file
*file
= r
->ee
->bprm
->file
;
251 realpath
= tomoyo_realpath_from_path(&file
->f_path
);
252 bprm_info
= tomoyo_print_bprm(r
->ee
->bprm
, &r
->ee
->dump
);
253 if (!realpath
|| !bprm_info
)
255 /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
256 len
+= strlen(realpath
) + 80 + strlen(bprm_info
);
257 } else if (r
->obj
&& r
->obj
->symlink_target
) {
258 symlink
= r
->obj
->symlink_target
->name
;
259 /* +18 is for " symlink.target=\"%s\"" */
260 len
+= 18 + strlen(symlink
);
262 len
= tomoyo_round2(len
);
263 buf
= kzalloc(len
, GFP_NOFS
);
267 pos
= snprintf(buf
, len
, "%s", header
);
269 struct linux_binprm
*bprm
= r
->ee
->bprm
;
270 pos
+= snprintf(buf
+ pos
, len
- pos
,
271 " exec={ realpath=\"%s\" argc=%d envc=%d %s }",
272 realpath
, bprm
->argc
, bprm
->envc
, bprm_info
);
274 pos
+= snprintf(buf
+ pos
, len
- pos
, " symlink.target=\"%s\"",
276 pos
+= snprintf(buf
+ pos
, len
- pos
, "\n%s\n", domainname
);
277 vsnprintf(buf
+ pos
, len
- pos
, fmt
, args
);
285 /* Wait queue for /sys/kernel/security/tomoyo/audit. */
286 static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait
);
288 /* Structure for audit log. */
290 struct list_head list
;
295 /* The list for "struct tomoyo_log". */
296 static LIST_HEAD(tomoyo_log
);
298 /* Lock for "struct list_head tomoyo_log". */
299 static DEFINE_SPINLOCK(tomoyo_log_lock
);
301 /* Length of "stuct list_head tomoyo_log". */
302 static unsigned int tomoyo_log_count
;
305 * tomoyo_get_audit - Get audit mode.
307 * @ns: Pointer to "struct tomoyo_policy_namespace".
308 * @profile: Profile number.
309 * @index: Index number of functionality.
310 * @is_granted: True if granted log, false otherwise.
312 * Returns true if this request should be audited, false otherwise.
314 static bool tomoyo_get_audit(const struct tomoyo_policy_namespace
*ns
,
315 const u8 profile
, const u8 index
,
316 const struct tomoyo_acl_info
*matched_acl
,
317 const bool is_granted
)
320 const u8 category
= tomoyo_index2category
[index
] +
321 TOMOYO_MAX_MAC_INDEX
;
322 struct tomoyo_profile
*p
;
323 if (!tomoyo_policy_loaded
)
325 p
= tomoyo_profile(ns
, profile
);
326 if (tomoyo_log_count
>= p
->pref
[TOMOYO_PREF_MAX_AUDIT_LOG
])
328 if (is_granted
&& matched_acl
&& matched_acl
->cond
&&
329 matched_acl
->cond
->grant_log
!= TOMOYO_GRANTLOG_AUTO
)
330 return matched_acl
->cond
->grant_log
== TOMOYO_GRANTLOG_YES
;
331 mode
= p
->config
[index
];
332 if (mode
== TOMOYO_CONFIG_USE_DEFAULT
)
333 mode
= p
->config
[category
];
334 if (mode
== TOMOYO_CONFIG_USE_DEFAULT
)
335 mode
= p
->default_config
;
337 return mode
& TOMOYO_CONFIG_WANT_GRANT_LOG
;
338 return mode
& TOMOYO_CONFIG_WANT_REJECT_LOG
;
342 * tomoyo_write_log2 - Write an audit log.
344 * @r: Pointer to "struct tomoyo_request_info".
345 * @len: Buffer size needed for @fmt and @args.
346 * @fmt: The printf()'s format string.
347 * @args: va_list structure for @fmt.
351 void tomoyo_write_log2(struct tomoyo_request_info
*r
, int len
, const char *fmt
,
355 struct tomoyo_log
*entry
;
356 bool quota_exceeded
= false;
357 if (!tomoyo_get_audit(r
->domain
->ns
, r
->profile
, r
->type
,
358 r
->matched_acl
, r
->granted
))
360 buf
= tomoyo_init_log(r
, len
, fmt
, args
);
363 entry
= kzalloc(sizeof(*entry
), GFP_NOFS
);
369 len
= tomoyo_round2(strlen(buf
) + 1);
371 * The entry->size is used for memory quota checks.
372 * Don't go beyond strlen(entry->log).
374 entry
->size
= len
+ tomoyo_round2(sizeof(*entry
));
375 spin_lock(&tomoyo_log_lock
);
376 if (tomoyo_memory_quota
[TOMOYO_MEMORY_AUDIT
] &&
377 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] + entry
->size
>=
378 tomoyo_memory_quota
[TOMOYO_MEMORY_AUDIT
]) {
379 quota_exceeded
= true;
381 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] += entry
->size
;
382 list_add_tail(&entry
->list
, &tomoyo_log
);
385 spin_unlock(&tomoyo_log_lock
);
386 if (quota_exceeded
) {
391 wake_up(&tomoyo_log_wait
);
397 * tomoyo_write_log - Write an audit log.
399 * @r: Pointer to "struct tomoyo_request_info".
400 * @fmt: The printf()'s format string, followed by parameters.
404 void tomoyo_write_log(struct tomoyo_request_info
*r
, const char *fmt
, ...)
409 len
= vsnprintf((char *) &len
, 1, fmt
, args
) + 1;
412 tomoyo_write_log2(r
, len
, fmt
, args
);
417 * tomoyo_read_log - Read an audit log.
419 * @head: Pointer to "struct tomoyo_io_buffer".
423 void tomoyo_read_log(struct tomoyo_io_buffer
*head
)
425 struct tomoyo_log
*ptr
= NULL
;
428 kfree(head
->read_buf
);
429 head
->read_buf
= NULL
;
430 spin_lock(&tomoyo_log_lock
);
431 if (!list_empty(&tomoyo_log
)) {
432 ptr
= list_entry(tomoyo_log
.next
, typeof(*ptr
), list
);
433 list_del(&ptr
->list
);
435 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] -= ptr
->size
;
437 spin_unlock(&tomoyo_log_lock
);
439 head
->read_buf
= ptr
->log
;
440 head
->r
.w
[head
->r
.w_pos
++] = head
->read_buf
;
446 * tomoyo_poll_log - Wait for an audit log.
448 * @file: Pointer to "struct file".
449 * @wait: Pointer to "poll_table". Maybe NULL.
451 * Returns POLLIN | POLLRDNORM when ready to read an audit log.
453 unsigned int tomoyo_poll_log(struct file
*file
, poll_table
*wait
)
455 if (tomoyo_log_count
)
456 return POLLIN
| POLLRDNORM
;
457 poll_wait(file
, &tomoyo_log_wait
, wait
);
458 if (tomoyo_log_count
)
459 return POLLIN
| POLLRDNORM
;