1 // SPDX-License-Identifier: GPL-2.0
3 * security/tomoyo/audit.c
5 * Copyright (C) 2005-2011 NTT DATA CORPORATION
9 #include <linux/slab.h>
12 * tomoyo_print_bprm - Print "struct linux_binprm" for auditing.
14 * @bprm: Pointer to "struct linux_binprm".
15 * @dump: Pointer to "struct tomoyo_page_dump".
17 * Returns the contents of @bprm on success, NULL otherwise.
19 * This function uses kzalloc(), so caller must kfree() if this function
22 static char *tomoyo_print_bprm(struct linux_binprm
*bprm
,
23 struct tomoyo_page_dump
*dump
)
25 static const int tomoyo_buffer_len
= 4096 * 2;
26 char *buffer
= kzalloc(tomoyo_buffer_len
, GFP_NOFS
);
30 unsigned long pos
= bprm
->p
;
31 int offset
= pos
% PAGE_SIZE
;
32 int argv_count
= bprm
->argc
;
33 int envp_count
= bprm
->envc
;
34 bool truncated
= false;
37 len
= snprintf(buffer
, tomoyo_buffer_len
- 1, "argv[]={ ");
40 memmove(cp
, "} envp[]={ ", 11);
44 while (argv_count
|| envp_count
) {
45 if (!tomoyo_dump_page(bprm
, pos
, dump
))
47 pos
+= PAGE_SIZE
- offset
;
49 while (offset
< PAGE_SIZE
) {
50 const char *kaddr
= dump
->data
;
51 const unsigned char c
= kaddr
[offset
++];
54 if (cp
>= buffer
+ tomoyo_buffer_len
- 32) {
55 /* Reserve some room for "..." string. */
57 } else if (c
== '\\') {
60 } else if (c
> ' ' && c
< 127) {
68 *cp
++ = (c
>> 6) + '0';
69 *cp
++ = ((c
>> 3) & 7) + '0';
70 *cp
++ = (c
& 7) + '0';
75 if (--argv_count
== 0) {
78 memmove(cp
, "... ", 4);
81 memmove(cp
, "} envp[]={ ", 11);
86 } else if (envp_count
) {
87 if (--envp_count
== 0) {
90 memmove(cp
, "... ", 4);
95 if (!argv_count
&& !envp_count
)
104 snprintf(buffer
, tomoyo_buffer_len
- 1,
105 "argv[]={ ... } envp[]= { ... }");
110 * tomoyo_filetype - Get string representation of file type.
112 * @mode: Mode value for stat().
114 * Returns file type string.
116 static inline const char *tomoyo_filetype(const umode_t mode
)
118 switch (mode
& S_IFMT
) {
121 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_FILE
];
123 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_DIRECTORY
];
125 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_SYMLINK
];
127 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_FIFO
];
129 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_SOCKET
];
131 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_BLOCK_DEV
];
133 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_CHAR_DEV
];
135 return "unknown"; /* This should not happen. */
139 * tomoyo_print_header - Get header line of audit log.
141 * @r: Pointer to "struct tomoyo_request_info".
143 * Returns string representation.
145 * This function uses kmalloc(), so caller must kfree() if this function
146 * didn't return NULL.
148 static char *tomoyo_print_header(struct tomoyo_request_info
*r
)
150 struct tomoyo_time stamp
;
151 const pid_t gpid
= task_pid_nr(current
);
152 struct tomoyo_obj_info
*obj
= r
->obj
;
153 static const int tomoyo_buffer_len
= 4096;
154 char *buffer
= kmalloc(tomoyo_buffer_len
, GFP_NOFS
);
160 tomoyo_convert_time(ktime_get_real_seconds(), &stamp
);
162 pos
= snprintf(buffer
, tomoyo_buffer_len
- 1,
163 "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
164 "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
165 "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
166 "fsuid=%u fsgid=%u }", stamp
.year
, stamp
.month
,
167 stamp
.day
, stamp
.hour
, stamp
.min
, stamp
.sec
, r
->profile
,
168 tomoyo_mode
[r
->mode
], tomoyo_yesno(r
->granted
), gpid
,
169 tomoyo_sys_getpid(), tomoyo_sys_getppid(),
170 from_kuid(&init_user_ns
, current_uid()),
171 from_kgid(&init_user_ns
, current_gid()),
172 from_kuid(&init_user_ns
, current_euid()),
173 from_kgid(&init_user_ns
, current_egid()),
174 from_kuid(&init_user_ns
, current_suid()),
175 from_kgid(&init_user_ns
, current_sgid()),
176 from_kuid(&init_user_ns
, current_fsuid()),
177 from_kgid(&init_user_ns
, current_fsgid()));
180 if (!obj
->validate_done
) {
181 tomoyo_get_attributes(obj
);
182 obj
->validate_done
= true;
184 for (i
= 0; i
< TOMOYO_MAX_PATH_STAT
; i
++) {
185 struct tomoyo_mini_stat
*stat
;
188 if (!obj
->stat_valid
[i
])
190 stat
= &obj
->stat
[i
];
194 pos
+= snprintf(buffer
+ pos
,
195 tomoyo_buffer_len
- 1 - pos
,
196 " path%u.parent={ uid=%u gid=%u "
197 "ino=%lu perm=0%o }", (i
>> 1) + 1,
198 from_kuid(&init_user_ns
, stat
->uid
),
199 from_kgid(&init_user_ns
, stat
->gid
),
200 (unsigned long)stat
->ino
,
201 stat
->mode
& S_IALLUGO
);
204 pos
+= snprintf(buffer
+ pos
, tomoyo_buffer_len
- 1 - pos
,
205 " path%u={ uid=%u gid=%u ino=%lu major=%u"
206 " minor=%u perm=0%o type=%s", (i
>> 1) + 1,
207 from_kuid(&init_user_ns
, stat
->uid
),
208 from_kgid(&init_user_ns
, stat
->gid
),
209 (unsigned long)stat
->ino
,
210 MAJOR(dev
), MINOR(dev
),
211 mode
& S_IALLUGO
, tomoyo_filetype(mode
));
212 if (S_ISCHR(mode
) || S_ISBLK(mode
)) {
214 pos
+= snprintf(buffer
+ pos
,
215 tomoyo_buffer_len
- 1 - pos
,
216 " dev_major=%u dev_minor=%u",
217 MAJOR(dev
), MINOR(dev
));
219 pos
+= snprintf(buffer
+ pos
, tomoyo_buffer_len
- 1 - pos
,
223 if (pos
< tomoyo_buffer_len
- 1)
230 * tomoyo_init_log - Allocate buffer for audit logs.
232 * @r: Pointer to "struct tomoyo_request_info".
233 * @len: Buffer size needed for @fmt and @args.
234 * @fmt: The printf()'s format string.
235 * @args: va_list structure for @fmt.
237 * Returns pointer to allocated memory.
239 * This function uses kzalloc(), so caller must kfree() if this function
240 * didn't return NULL.
242 char *tomoyo_init_log(struct tomoyo_request_info
*r
, int len
, const char *fmt
,
246 char *bprm_info
= NULL
;
247 const char *header
= NULL
;
248 char *realpath
= NULL
;
249 const char *symlink
= NULL
;
251 const char *domainname
= r
->domain
->domainname
->name
;
252 header
= tomoyo_print_header(r
);
255 /* +10 is for '\n' etc. and '\0'. */
256 len
+= strlen(domainname
) + strlen(header
) + 10;
258 struct file
*file
= r
->ee
->bprm
->file
;
259 realpath
= tomoyo_realpath_from_path(&file
->f_path
);
260 bprm_info
= tomoyo_print_bprm(r
->ee
->bprm
, &r
->ee
->dump
);
261 if (!realpath
|| !bprm_info
)
263 /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
264 len
+= strlen(realpath
) + 80 + strlen(bprm_info
);
265 } else if (r
->obj
&& r
->obj
->symlink_target
) {
266 symlink
= r
->obj
->symlink_target
->name
;
267 /* +18 is for " symlink.target=\"%s\"" */
268 len
+= 18 + strlen(symlink
);
270 len
= tomoyo_round2(len
);
271 buf
= kzalloc(len
, GFP_NOFS
);
275 pos
= snprintf(buf
, len
, "%s", header
);
277 struct linux_binprm
*bprm
= r
->ee
->bprm
;
278 pos
+= snprintf(buf
+ pos
, len
- pos
,
279 " exec={ realpath=\"%s\" argc=%d envc=%d %s }",
280 realpath
, bprm
->argc
, bprm
->envc
, bprm_info
);
282 pos
+= snprintf(buf
+ pos
, len
- pos
, " symlink.target=\"%s\"",
284 pos
+= snprintf(buf
+ pos
, len
- pos
, "\n%s\n", domainname
);
285 vsnprintf(buf
+ pos
, len
- pos
, fmt
, args
);
293 /* Wait queue for /sys/kernel/security/tomoyo/audit. */
294 static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait
);
296 /* Structure for audit log. */
298 struct list_head list
;
303 /* The list for "struct tomoyo_log". */
304 static LIST_HEAD(tomoyo_log
);
306 /* Lock for "struct list_head tomoyo_log". */
307 static DEFINE_SPINLOCK(tomoyo_log_lock
);
309 /* Length of "stuct list_head tomoyo_log". */
310 static unsigned int tomoyo_log_count
;
313 * tomoyo_get_audit - Get audit mode.
315 * @ns: Pointer to "struct tomoyo_policy_namespace".
316 * @profile: Profile number.
317 * @index: Index number of functionality.
318 * @is_granted: True if granted log, false otherwise.
320 * Returns true if this request should be audited, false otherwise.
322 static bool tomoyo_get_audit(const struct tomoyo_policy_namespace
*ns
,
323 const u8 profile
, const u8 index
,
324 const struct tomoyo_acl_info
*matched_acl
,
325 const bool is_granted
)
328 const u8 category
= tomoyo_index2category
[index
] +
329 TOMOYO_MAX_MAC_INDEX
;
330 struct tomoyo_profile
*p
;
331 if (!tomoyo_policy_loaded
)
333 p
= tomoyo_profile(ns
, profile
);
334 if (tomoyo_log_count
>= p
->pref
[TOMOYO_PREF_MAX_AUDIT_LOG
])
336 if (is_granted
&& matched_acl
&& matched_acl
->cond
&&
337 matched_acl
->cond
->grant_log
!= TOMOYO_GRANTLOG_AUTO
)
338 return matched_acl
->cond
->grant_log
== TOMOYO_GRANTLOG_YES
;
339 mode
= p
->config
[index
];
340 if (mode
== TOMOYO_CONFIG_USE_DEFAULT
)
341 mode
= p
->config
[category
];
342 if (mode
== TOMOYO_CONFIG_USE_DEFAULT
)
343 mode
= p
->default_config
;
345 return mode
& TOMOYO_CONFIG_WANT_GRANT_LOG
;
346 return mode
& TOMOYO_CONFIG_WANT_REJECT_LOG
;
350 * tomoyo_write_log2 - Write an audit log.
352 * @r: Pointer to "struct tomoyo_request_info".
353 * @len: Buffer size needed for @fmt and @args.
354 * @fmt: The printf()'s format string.
355 * @args: va_list structure for @fmt.
359 void tomoyo_write_log2(struct tomoyo_request_info
*r
, int len
, const char *fmt
,
363 struct tomoyo_log
*entry
;
364 bool quota_exceeded
= false;
365 if (!tomoyo_get_audit(r
->domain
->ns
, r
->profile
, r
->type
,
366 r
->matched_acl
, r
->granted
))
368 buf
= tomoyo_init_log(r
, len
, fmt
, args
);
371 entry
= kzalloc(sizeof(*entry
), GFP_NOFS
);
377 len
= tomoyo_round2(strlen(buf
) + 1);
379 * The entry->size is used for memory quota checks.
380 * Don't go beyond strlen(entry->log).
382 entry
->size
= len
+ tomoyo_round2(sizeof(*entry
));
383 spin_lock(&tomoyo_log_lock
);
384 if (tomoyo_memory_quota
[TOMOYO_MEMORY_AUDIT
] &&
385 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] + entry
->size
>=
386 tomoyo_memory_quota
[TOMOYO_MEMORY_AUDIT
]) {
387 quota_exceeded
= true;
389 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] += entry
->size
;
390 list_add_tail(&entry
->list
, &tomoyo_log
);
393 spin_unlock(&tomoyo_log_lock
);
394 if (quota_exceeded
) {
399 wake_up(&tomoyo_log_wait
);
405 * tomoyo_write_log - Write an audit log.
407 * @r: Pointer to "struct tomoyo_request_info".
408 * @fmt: The printf()'s format string, followed by parameters.
412 void tomoyo_write_log(struct tomoyo_request_info
*r
, const char *fmt
, ...)
417 len
= vsnprintf((char *) &len
, 1, fmt
, args
) + 1;
420 tomoyo_write_log2(r
, len
, fmt
, args
);
425 * tomoyo_read_log - Read an audit log.
427 * @head: Pointer to "struct tomoyo_io_buffer".
431 void tomoyo_read_log(struct tomoyo_io_buffer
*head
)
433 struct tomoyo_log
*ptr
= NULL
;
436 kfree(head
->read_buf
);
437 head
->read_buf
= NULL
;
438 spin_lock(&tomoyo_log_lock
);
439 if (!list_empty(&tomoyo_log
)) {
440 ptr
= list_entry(tomoyo_log
.next
, typeof(*ptr
), list
);
441 list_del(&ptr
->list
);
443 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] -= ptr
->size
;
445 spin_unlock(&tomoyo_log_lock
);
447 head
->read_buf
= ptr
->log
;
448 head
->r
.w
[head
->r
.w_pos
++] = head
->read_buf
;
454 * tomoyo_poll_log - Wait for an audit log.
456 * @file: Pointer to "struct file".
457 * @wait: Pointer to "poll_table". Maybe NULL.
459 * Returns EPOLLIN | EPOLLRDNORM when ready to read an audit log.
461 __poll_t
tomoyo_poll_log(struct file
*file
, poll_table
*wait
)
463 if (tomoyo_log_count
)
464 return EPOLLIN
| EPOLLRDNORM
;
465 poll_wait(file
, &tomoyo_log_wait
, wait
);
466 if (tomoyo_log_count
)
467 return EPOLLIN
| EPOLLRDNORM
;