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;
38 len
= snprintf(buffer
, tomoyo_buffer_len
- 1, "argv[]={ ");
41 memmove(cp
, "} envp[]={ ", 11);
45 while (argv_count
|| envp_count
) {
46 if (!tomoyo_dump_page(bprm
, pos
, dump
))
48 pos
+= PAGE_SIZE
- offset
;
50 while (offset
< PAGE_SIZE
) {
51 const char *kaddr
= dump
->data
;
52 const unsigned char c
= kaddr
[offset
++];
56 if (cp
>= buffer
+ tomoyo_buffer_len
- 32) {
57 /* Reserve some room for "..." string. */
59 } else if (c
== '\\') {
62 } else if (c
> ' ' && c
< 127) {
70 *cp
++ = (c
>> 6) + '0';
71 *cp
++ = ((c
>> 3) & 7) + '0';
72 *cp
++ = (c
& 7) + '0';
77 if (--argv_count
== 0) {
80 memmove(cp
, "... ", 4);
83 memmove(cp
, "} envp[]={ ", 11);
88 } else if (envp_count
) {
89 if (--envp_count
== 0) {
92 memmove(cp
, "... ", 4);
97 if (!argv_count
&& !envp_count
)
106 snprintf(buffer
, tomoyo_buffer_len
- 1,
107 "argv[]={ ... } envp[]= { ... }");
112 * tomoyo_filetype - Get string representation of file type.
114 * @mode: Mode value for stat().
116 * Returns file type string.
118 static inline const char *tomoyo_filetype(const umode_t mode
)
120 switch (mode
& S_IFMT
) {
123 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_FILE
];
125 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_DIRECTORY
];
127 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_SYMLINK
];
129 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_FIFO
];
131 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_SOCKET
];
133 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_BLOCK_DEV
];
135 return tomoyo_condition_keyword
[TOMOYO_TYPE_IS_CHAR_DEV
];
137 return "unknown"; /* This should not happen. */
141 * tomoyo_print_header - Get header line of audit log.
143 * @r: Pointer to "struct tomoyo_request_info".
145 * Returns string representation.
147 * This function uses kmalloc(), so caller must kfree() if this function
148 * didn't return NULL.
150 static char *tomoyo_print_header(struct tomoyo_request_info
*r
)
152 struct tomoyo_time stamp
;
153 const pid_t gpid
= task_pid_nr(current
);
154 struct tomoyo_obj_info
*obj
= r
->obj
;
155 static const int tomoyo_buffer_len
= 4096;
156 char *buffer
= kmalloc(tomoyo_buffer_len
, GFP_NOFS
);
163 tomoyo_convert_time(ktime_get_real_seconds(), &stamp
);
165 pos
= snprintf(buffer
, tomoyo_buffer_len
- 1,
166 "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s granted=%s (global-pid=%u) task={ pid=%u ppid=%u uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }",
167 stamp
.year
, stamp
.month
, stamp
.day
, stamp
.hour
,
168 stamp
.min
, stamp
.sec
, r
->profile
, tomoyo_mode
[r
->mode
],
169 tomoyo_yesno(r
->granted
), gpid
, tomoyo_sys_getpid(),
170 tomoyo_sys_getppid(),
171 from_kuid(&init_user_ns
, current_uid()),
172 from_kgid(&init_user_ns
, current_gid()),
173 from_kuid(&init_user_ns
, current_euid()),
174 from_kgid(&init_user_ns
, current_egid()),
175 from_kuid(&init_user_ns
, current_suid()),
176 from_kgid(&init_user_ns
, current_sgid()),
177 from_kuid(&init_user_ns
, current_fsuid()),
178 from_kgid(&init_user_ns
, current_fsgid()));
181 if (!obj
->validate_done
) {
182 tomoyo_get_attributes(obj
);
183 obj
->validate_done
= true;
185 for (i
= 0; i
< TOMOYO_MAX_PATH_STAT
; i
++) {
186 struct tomoyo_mini_stat
*stat
;
190 if (!obj
->stat_valid
[i
])
192 stat
= &obj
->stat
[i
];
196 pos
+= snprintf(buffer
+ pos
,
197 tomoyo_buffer_len
- 1 - pos
,
198 " path%u.parent={ uid=%u gid=%u ino=%lu perm=0%o }",
200 from_kuid(&init_user_ns
, stat
->uid
),
201 from_kgid(&init_user_ns
, stat
->gid
),
202 (unsigned long)stat
->ino
,
203 stat
->mode
& S_IALLUGO
);
206 pos
+= snprintf(buffer
+ pos
, tomoyo_buffer_len
- 1 - pos
,
207 " path%u={ uid=%u gid=%u ino=%lu major=%u minor=%u perm=0%o type=%s",
209 from_kuid(&init_user_ns
, stat
->uid
),
210 from_kgid(&init_user_ns
, stat
->gid
),
211 (unsigned long)stat
->ino
,
212 MAJOR(dev
), MINOR(dev
),
213 mode
& S_IALLUGO
, tomoyo_filetype(mode
));
214 if (S_ISCHR(mode
) || S_ISBLK(mode
)) {
216 pos
+= snprintf(buffer
+ pos
,
217 tomoyo_buffer_len
- 1 - pos
,
218 " dev_major=%u dev_minor=%u",
219 MAJOR(dev
), MINOR(dev
));
221 pos
+= snprintf(buffer
+ pos
, tomoyo_buffer_len
- 1 - pos
,
225 if (pos
< tomoyo_buffer_len
- 1)
232 * tomoyo_init_log - Allocate buffer for audit logs.
234 * @r: Pointer to "struct tomoyo_request_info".
235 * @len: Buffer size needed for @fmt and @args.
236 * @fmt: The printf()'s format string.
237 * @args: va_list structure for @fmt.
239 * Returns pointer to allocated memory.
241 * This function uses kzalloc(), so caller must kfree() if this function
242 * didn't return NULL.
244 char *tomoyo_init_log(struct tomoyo_request_info
*r
, int len
, const char *fmt
,
248 char *bprm_info
= NULL
;
249 const char *header
= NULL
;
250 char *realpath
= NULL
;
251 const char *symlink
= NULL
;
253 const char *domainname
= r
->domain
->domainname
->name
;
255 header
= tomoyo_print_header(r
);
258 /* +10 is for '\n' etc. and '\0'. */
259 len
+= strlen(domainname
) + strlen(header
) + 10;
261 struct file
*file
= r
->ee
->bprm
->file
;
263 realpath
= tomoyo_realpath_from_path(&file
->f_path
);
264 bprm_info
= tomoyo_print_bprm(r
->ee
->bprm
, &r
->ee
->dump
);
265 if (!realpath
|| !bprm_info
)
267 /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
268 len
+= strlen(realpath
) + 80 + strlen(bprm_info
);
269 } else if (r
->obj
&& r
->obj
->symlink_target
) {
270 symlink
= r
->obj
->symlink_target
->name
;
271 /* +18 is for " symlink.target=\"%s\"" */
272 len
+= 18 + strlen(symlink
);
274 len
= tomoyo_round2(len
);
275 buf
= kzalloc(len
, GFP_NOFS
);
279 pos
= snprintf(buf
, len
, "%s", header
);
281 struct linux_binprm
*bprm
= r
->ee
->bprm
;
283 pos
+= snprintf(buf
+ pos
, len
- pos
,
284 " exec={ realpath=\"%s\" argc=%d envc=%d %s }",
285 realpath
, bprm
->argc
, bprm
->envc
, bprm_info
);
287 pos
+= snprintf(buf
+ pos
, len
- pos
, " symlink.target=\"%s\"",
289 pos
+= snprintf(buf
+ pos
, len
- pos
, "\n%s\n", domainname
);
290 vsnprintf(buf
+ pos
, len
- pos
, fmt
, args
);
298 /* Wait queue for /sys/kernel/security/tomoyo/audit. */
299 static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait
);
301 /* Structure for audit log. */
303 struct list_head list
;
308 /* The list for "struct tomoyo_log". */
309 static LIST_HEAD(tomoyo_log
);
311 /* Lock for "struct list_head tomoyo_log". */
312 static DEFINE_SPINLOCK(tomoyo_log_lock
);
314 /* Length of "struct list_head tomoyo_log". */
315 static unsigned int tomoyo_log_count
;
318 * tomoyo_get_audit - Get audit mode.
320 * @ns: Pointer to "struct tomoyo_policy_namespace".
321 * @profile: Profile number.
322 * @index: Index number of functionality.
323 * @is_granted: True if granted log, false otherwise.
325 * Returns true if this request should be audited, false otherwise.
327 static bool tomoyo_get_audit(const struct tomoyo_policy_namespace
*ns
,
328 const u8 profile
, const u8 index
,
329 const struct tomoyo_acl_info
*matched_acl
,
330 const bool is_granted
)
333 const u8 category
= tomoyo_index2category
[index
] +
334 TOMOYO_MAX_MAC_INDEX
;
335 struct tomoyo_profile
*p
;
337 if (!tomoyo_policy_loaded
)
339 p
= tomoyo_profile(ns
, profile
);
340 if (tomoyo_log_count
>= p
->pref
[TOMOYO_PREF_MAX_AUDIT_LOG
])
342 if (is_granted
&& matched_acl
&& matched_acl
->cond
&&
343 matched_acl
->cond
->grant_log
!= TOMOYO_GRANTLOG_AUTO
)
344 return matched_acl
->cond
->grant_log
== TOMOYO_GRANTLOG_YES
;
345 mode
= p
->config
[index
];
346 if (mode
== TOMOYO_CONFIG_USE_DEFAULT
)
347 mode
= p
->config
[category
];
348 if (mode
== TOMOYO_CONFIG_USE_DEFAULT
)
349 mode
= p
->default_config
;
351 return mode
& TOMOYO_CONFIG_WANT_GRANT_LOG
;
352 return mode
& TOMOYO_CONFIG_WANT_REJECT_LOG
;
356 * tomoyo_write_log2 - Write an audit log.
358 * @r: Pointer to "struct tomoyo_request_info".
359 * @len: Buffer size needed for @fmt and @args.
360 * @fmt: The printf()'s format string.
361 * @args: va_list structure for @fmt.
365 void tomoyo_write_log2(struct tomoyo_request_info
*r
, int len
, const char *fmt
,
369 struct tomoyo_log
*entry
;
370 bool quota_exceeded
= false;
372 if (!tomoyo_get_audit(r
->domain
->ns
, r
->profile
, r
->type
,
373 r
->matched_acl
, r
->granted
))
375 buf
= tomoyo_init_log(r
, len
, fmt
, args
);
378 entry
= kzalloc(sizeof(*entry
), GFP_NOFS
);
384 len
= tomoyo_round2(strlen(buf
) + 1);
386 * The entry->size is used for memory quota checks.
387 * Don't go beyond strlen(entry->log).
389 entry
->size
= len
+ tomoyo_round2(sizeof(*entry
));
390 spin_lock(&tomoyo_log_lock
);
391 if (tomoyo_memory_quota
[TOMOYO_MEMORY_AUDIT
] &&
392 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] + entry
->size
>=
393 tomoyo_memory_quota
[TOMOYO_MEMORY_AUDIT
]) {
394 quota_exceeded
= true;
396 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] += entry
->size
;
397 list_add_tail(&entry
->list
, &tomoyo_log
);
400 spin_unlock(&tomoyo_log_lock
);
401 if (quota_exceeded
) {
406 wake_up(&tomoyo_log_wait
);
412 * tomoyo_write_log - Write an audit log.
414 * @r: Pointer to "struct tomoyo_request_info".
415 * @fmt: The printf()'s format string, followed by parameters.
419 void tomoyo_write_log(struct tomoyo_request_info
*r
, const char *fmt
, ...)
425 len
= vsnprintf((char *) &len
, 1, fmt
, args
) + 1;
428 tomoyo_write_log2(r
, len
, fmt
, args
);
433 * tomoyo_read_log - Read an audit log.
435 * @head: Pointer to "struct tomoyo_io_buffer".
439 void tomoyo_read_log(struct tomoyo_io_buffer
*head
)
441 struct tomoyo_log
*ptr
= NULL
;
445 kfree(head
->read_buf
);
446 head
->read_buf
= NULL
;
447 spin_lock(&tomoyo_log_lock
);
448 if (!list_empty(&tomoyo_log
)) {
449 ptr
= list_entry(tomoyo_log
.next
, typeof(*ptr
), list
);
450 list_del(&ptr
->list
);
452 tomoyo_memory_used
[TOMOYO_MEMORY_AUDIT
] -= ptr
->size
;
454 spin_unlock(&tomoyo_log_lock
);
456 head
->read_buf
= ptr
->log
;
457 head
->r
.w
[head
->r
.w_pos
++] = head
->read_buf
;
463 * tomoyo_poll_log - Wait for an audit log.
465 * @file: Pointer to "struct file".
466 * @wait: Pointer to "poll_table". Maybe NULL.
468 * Returns EPOLLIN | EPOLLRDNORM when ready to read an audit log.
470 __poll_t
tomoyo_poll_log(struct file
*file
, poll_table
*wait
)
472 if (tomoyo_log_count
)
473 return EPOLLIN
| EPOLLRDNORM
;
474 poll_wait(file
, &tomoyo_log_wait
, wait
);
475 if (tomoyo_log_count
)
476 return EPOLLIN
| EPOLLRDNORM
;