1eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/*
2eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * security/tomoyo/audit.c
3eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
40f2a55d5bb2372058275b0b343d90dd5d640d045Tetsuo Handa * Copyright (C) 2005-2011  NTT DATA CORPORATION
5eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
6eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
7eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa#include "common.h"
8eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa#include <linux/slab.h>
9eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
10eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
115b636857fee642694e287e3a181b523b16098c93Tetsuo Handa * tomoyo_print_bprm - Print "struct linux_binprm" for auditing.
125b636857fee642694e287e3a181b523b16098c93Tetsuo Handa *
135b636857fee642694e287e3a181b523b16098c93Tetsuo Handa * @bprm: Pointer to "struct linux_binprm".
145b636857fee642694e287e3a181b523b16098c93Tetsuo Handa * @dump: Pointer to "struct tomoyo_page_dump".
155b636857fee642694e287e3a181b523b16098c93Tetsuo Handa *
165b636857fee642694e287e3a181b523b16098c93Tetsuo Handa * Returns the contents of @bprm on success, NULL otherwise.
175b636857fee642694e287e3a181b523b16098c93Tetsuo Handa *
185b636857fee642694e287e3a181b523b16098c93Tetsuo Handa * This function uses kzalloc(), so caller must kfree() if this function
195b636857fee642694e287e3a181b523b16098c93Tetsuo Handa * didn't return NULL.
205b636857fee642694e287e3a181b523b16098c93Tetsuo Handa */
215b636857fee642694e287e3a181b523b16098c93Tetsuo Handastatic char *tomoyo_print_bprm(struct linux_binprm *bprm,
225b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			       struct tomoyo_page_dump *dump)
235b636857fee642694e287e3a181b523b16098c93Tetsuo Handa{
245b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	static const int tomoyo_buffer_len = 4096 * 2;
255b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS);
265b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	char *cp;
275b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	char *last_start;
285b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	int len;
295b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	unsigned long pos = bprm->p;
305b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	int offset = pos % PAGE_SIZE;
315b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	int argv_count = bprm->argc;
325b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	int envp_count = bprm->envc;
335b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	bool truncated = false;
345b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	if (!buffer)
355b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		return NULL;
365b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ ");
375b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	cp = buffer + len;
385b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	if (!argv_count) {
395b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		memmove(cp, "} envp[]={ ", 11);
405b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		cp += 11;
415b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	}
425b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	last_start = cp;
435b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	while (argv_count || envp_count) {
445b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		if (!tomoyo_dump_page(bprm, pos, dump))
455b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			goto out;
465b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		pos += PAGE_SIZE - offset;
475b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		/* Read. */
485b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		while (offset < PAGE_SIZE) {
495b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			const char *kaddr = dump->data;
505b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			const unsigned char c = kaddr[offset++];
515b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			if (cp == last_start)
525b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = '"';
535b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			if (cp >= buffer + tomoyo_buffer_len - 32) {
545b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				/* Reserve some room for "..." string. */
555b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				truncated = true;
565b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			} else if (c == '\\') {
575b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = '\\';
585b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = '\\';
595b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			} else if (c > ' ' && c < 127) {
605b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = c;
615b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			} else if (!c) {
625b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = '"';
635b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = ' ';
645b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				last_start = cp;
655b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			} else {
665b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = '\\';
675b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = (c >> 6) + '0';
685b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = ((c >> 3) & 7) + '0';
695b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				*cp++ = (c & 7) + '0';
705b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			}
715b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			if (c)
725b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				continue;
735b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			if (argv_count) {
745b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				if (--argv_count == 0) {
755b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					if (truncated) {
765b636857fee642694e287e3a181b523b16098c93Tetsuo Handa						cp = last_start;
775b636857fee642694e287e3a181b523b16098c93Tetsuo Handa						memmove(cp, "... ", 4);
785b636857fee642694e287e3a181b523b16098c93Tetsuo Handa						cp += 4;
795b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					}
805b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					memmove(cp, "} envp[]={ ", 11);
815b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					cp += 11;
825b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					last_start = cp;
835b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					truncated = false;
845b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				}
855b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			} else if (envp_count) {
865b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				if (--envp_count == 0) {
875b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					if (truncated) {
885b636857fee642694e287e3a181b523b16098c93Tetsuo Handa						cp = last_start;
895b636857fee642694e287e3a181b523b16098c93Tetsuo Handa						memmove(cp, "... ", 4);
905b636857fee642694e287e3a181b523b16098c93Tetsuo Handa						cp += 4;
915b636857fee642694e287e3a181b523b16098c93Tetsuo Handa					}
925b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				}
935b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			}
945b636857fee642694e287e3a181b523b16098c93Tetsuo Handa			if (!argv_count && !envp_count)
955b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				break;
965b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		}
975b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		offset = 0;
985b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	}
995b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	*cp++ = '}';
1005b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	*cp = '\0';
1015b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	return buffer;
1025b636857fee642694e287e3a181b523b16098c93Tetsuo Handaout:
1035b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	snprintf(buffer, tomoyo_buffer_len - 1,
1045b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		 "argv[]={ ... } envp[]= { ... }");
1055b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	return buffer;
1065b636857fee642694e287e3a181b523b16098c93Tetsuo Handa}
1075b636857fee642694e287e3a181b523b16098c93Tetsuo Handa
1085b636857fee642694e287e3a181b523b16098c93Tetsuo Handa/**
1098761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa * tomoyo_filetype - Get string representation of file type.
1108761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa *
1118761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa * @mode: Mode value for stat().
1128761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa *
1138761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa * Returns file type string.
1148761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa */
115d179333f37d33533f4c77118f757b9e7835ccb7cAl Virostatic inline const char *tomoyo_filetype(const umode_t mode)
1168761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa{
1178761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	switch (mode & S_IFMT) {
1188761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFREG:
1198761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case 0:
1208761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE];
1218761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFDIR:
1228761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY];
1238761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFLNK:
1248761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK];
1258761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFIFO:
1268761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO];
1278761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFSOCK:
1288761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET];
1298761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFBLK:
1308761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV];
1318761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	case S_IFCHR:
1328761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV];
1338761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	}
1348761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	return "unknown"; /* This should not happen. */
1358761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa}
1368761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa
1378761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa/**
138eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_print_header - Get header line of audit log.
139eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
140eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @r: Pointer to "struct tomoyo_request_info".
141eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
142eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns string representation.
143eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
144eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * This function uses kmalloc(), so caller must kfree() if this function
145eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * didn't return NULL.
146eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
147eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handastatic char *tomoyo_print_header(struct tomoyo_request_info *r)
148eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
149eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	struct tomoyo_time stamp;
150eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	const pid_t gpid = task_pid_nr(current);
1518761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	struct tomoyo_obj_info *obj = r->obj;
152eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	static const int tomoyo_buffer_len = 4096;
153eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS);
1542066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa	int pos;
1558761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	u8 i;
156eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!buffer)
157eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return NULL;
15877f4fa089c724adc3a87c10eb031bca91b144ac0Thomas Gleixner
15977f4fa089c724adc3a87c10eb031bca91b144ac0Thomas Gleixner	tomoyo_convert_time(get_seconds(), &stamp);
16077f4fa089c724adc3a87c10eb031bca91b144ac0Thomas Gleixner
1612066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa	pos = snprintf(buffer, tomoyo_buffer_len - 1,
1622066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s "
1632066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       "granted=%s (global-pid=%u) task={ pid=%u ppid=%u "
1642066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       "uid=%u gid=%u euid=%u egid=%u suid=%u sgid=%u "
1652066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       "fsuid=%u fsgid=%u }", stamp.year, stamp.month,
1662066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile,
1672066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid,
1682066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		       tomoyo_sys_getpid(), tomoyo_sys_getppid(),
169609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kuid(&init_user_ns, current_uid()),
170609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kgid(&init_user_ns, current_gid()),
171609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kuid(&init_user_ns, current_euid()),
172609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kgid(&init_user_ns, current_egid()),
173609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kuid(&init_user_ns, current_suid()),
174609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kgid(&init_user_ns, current_sgid()),
175609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kuid(&init_user_ns, current_fsuid()),
176609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman		       from_kgid(&init_user_ns, current_fsgid()));
1778761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	if (!obj)
1788761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		goto no_obj_info;
1798761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	if (!obj->validate_done) {
1808761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		tomoyo_get_attributes(obj);
1818761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		obj->validate_done = true;
1828761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	}
1838761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) {
1848761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		struct tomoyo_mini_stat *stat;
1858761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		unsigned int dev;
186d179333f37d33533f4c77118f757b9e7835ccb7cAl Viro		umode_t mode;
1878761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		if (!obj->stat_valid[i])
1888761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa			continue;
1898761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		stat = &obj->stat[i];
1908761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		dev = stat->dev;
1918761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		mode = stat->mode;
1928761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		if (i & 1) {
1938761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa			pos += snprintf(buffer + pos,
1948761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa					tomoyo_buffer_len - 1 - pos,
1958761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa					" path%u.parent={ uid=%u gid=%u "
1968761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa					"ino=%lu perm=0%o }", (i >> 1) + 1,
197609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman					from_kuid(&init_user_ns, stat->uid),
198609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman					from_kgid(&init_user_ns, stat->gid),
199609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman					(unsigned long)stat->ino,
200609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman					stat->mode & S_IALLUGO);
2018761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa			continue;
2028761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		}
2038761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
2048761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa				" path%u={ uid=%u gid=%u ino=%lu major=%u"
2058761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa				" minor=%u perm=0%o type=%s", (i >> 1) + 1,
206609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman				from_kuid(&init_user_ns, stat->uid),
207609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman				from_kgid(&init_user_ns, stat->gid),
208609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman				(unsigned long)stat->ino,
209609fcd1b3a55f99667c61609895c83019b21baadEric W. Biederman				MAJOR(dev), MINOR(dev),
2108761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa				mode & S_IALLUGO, tomoyo_filetype(mode));
2118761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		if (S_ISCHR(mode) || S_ISBLK(mode)) {
2128761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa			dev = stat->rdev;
2138761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa			pos += snprintf(buffer + pos,
2148761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa					tomoyo_buffer_len - 1 - pos,
2158761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa					" dev_major=%u dev_minor=%u",
2168761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa					MAJOR(dev), MINOR(dev));
2178761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		}
2188761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa		pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos,
2198761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa				" }");
2208761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handa	}
2218761afd49ebff8ae04c1a7888af090177441d07dTetsuo Handano_obj_info:
2222066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa	if (pos < tomoyo_buffer_len - 1)
2232066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa		return buffer;
2242066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa	kfree(buffer);
2252066a36125fcbf5220990173b9d8e8bc49ad7538Tetsuo Handa	return NULL;
226eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
227eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
228eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
229eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_init_log - Allocate buffer for audit logs.
230eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
231eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @r:    Pointer to "struct tomoyo_request_info".
232eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @len:  Buffer size needed for @fmt and @args.
233eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @fmt:  The printf()'s format string.
234eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @args: va_list structure for @fmt.
235eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
236eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns pointer to allocated memory.
237eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
238eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * This function uses kzalloc(), so caller must kfree() if this function
239eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * didn't return NULL.
240eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
241eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handachar *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
242eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		      va_list args)
243eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
244eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	char *buf = NULL;
2455b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	char *bprm_info = NULL;
246eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	const char *header = NULL;
2472ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	char *realpath = NULL;
2482ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	const char *symlink = NULL;
249eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	int pos;
250ea504819122a76a236f8b95d1556f807a0a41397Tetsuo Handa	const char *domainname = r->domain->domainname->name;
251eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	header = tomoyo_print_header(r);
252eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!header)
253eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return NULL;
254eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	/* +10 is for '\n' etc. and '\0'. */
255eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	len += strlen(domainname) + strlen(header) + 10;
2562ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	if (r->ee) {
2572ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		struct file *file = r->ee->bprm->file;
2582ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		realpath = tomoyo_realpath_from_path(&file->f_path);
2595b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump);
2605b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		if (!realpath || !bprm_info)
2612ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa			goto out;
2625b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		/* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */
2635b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		len += strlen(realpath) + 80 + strlen(bprm_info);
2642ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	} else if (r->obj && r->obj->symlink_target) {
2652ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		symlink = r->obj->symlink_target->name;
2662ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		/* +18 is for " symlink.target=\"%s\"" */
2672ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		len += 18 + strlen(symlink);
2682ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	}
269eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	len = tomoyo_round2(len);
270eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	buf = kzalloc(len, GFP_NOFS);
271eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!buf)
272eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		goto out;
273eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	len--;
274eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	pos = snprintf(buf, len, "%s", header);
2752ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	if (realpath) {
2765b636857fee642694e287e3a181b523b16098c93Tetsuo Handa		struct linux_binprm *bprm = r->ee->bprm;
2772ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		pos += snprintf(buf + pos, len - pos,
2785b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				" exec={ realpath=\"%s\" argc=%d envc=%d %s }",
2795b636857fee642694e287e3a181b523b16098c93Tetsuo Handa				realpath, bprm->argc, bprm->envc, bprm_info);
2802ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	} else if (symlink)
2812ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa		pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"",
2822ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa				symlink);
283eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname);
284eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	vsnprintf(buf + pos, len - pos, fmt, args);
285eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handaout:
2862ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563Tetsuo Handa	kfree(realpath);
2875b636857fee642694e287e3a181b523b16098c93Tetsuo Handa	kfree(bprm_info);
288eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	kfree(header);
289eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	return buf;
290eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
291eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
292eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/* Wait queue for /sys/kernel/security/tomoyo/audit. */
293eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handastatic DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait);
294eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
295eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/* Structure for audit log. */
296eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handastruct tomoyo_log {
297eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	struct list_head list;
298eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	char *log;
299eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	int size;
300eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa};
301eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
302eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/* The list for "struct tomoyo_log". */
303eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handastatic LIST_HEAD(tomoyo_log);
304eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
305eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/* Lock for "struct list_head tomoyo_log". */
306eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handastatic DEFINE_SPINLOCK(tomoyo_log_lock);
307eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
308eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/* Length of "stuct list_head tomoyo_log". */
309eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handastatic unsigned int tomoyo_log_count;
310eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
311eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
312eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_get_audit - Get audit mode.
313eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
314bd03a3e4c9a9df0c6b007045fa7fc8889111a478Tetsuo Handa * @ns:          Pointer to "struct tomoyo_policy_namespace".
315eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @profile:     Profile number.
316eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @index:       Index number of functionality.
317eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @is_granted:  True if granted log, false otherwise.
318eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
319eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns true if this request should be audited, false otherwise.
320eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
321bd03a3e4c9a9df0c6b007045fa7fc8889111a478Tetsuo Handastatic bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns,
322bd03a3e4c9a9df0c6b007045fa7fc8889111a478Tetsuo Handa			     const u8 profile, const u8 index,
3231f067a682a9bd252107ac6f6946b7332fde42344Tetsuo Handa			     const struct tomoyo_acl_info *matched_acl,
324eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa			     const bool is_granted)
325eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
326eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	u8 mode;
3272c47ab9353242b0f061959318f83c55360b88fa4Tetsuo Handa	const u8 category = tomoyo_index2category[index] +
3282c47ab9353242b0f061959318f83c55360b88fa4Tetsuo Handa		TOMOYO_MAX_MAC_INDEX;
329eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	struct tomoyo_profile *p;
330eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!tomoyo_policy_loaded)
331eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return false;
332bd03a3e4c9a9df0c6b007045fa7fc8889111a478Tetsuo Handa	p = tomoyo_profile(ns, profile);
333eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG])
334eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return false;
3351f067a682a9bd252107ac6f6946b7332fde42344Tetsuo Handa	if (is_granted && matched_acl && matched_acl->cond &&
3361f067a682a9bd252107ac6f6946b7332fde42344Tetsuo Handa	    matched_acl->cond->grant_log != TOMOYO_GRANTLOG_AUTO)
3371f067a682a9bd252107ac6f6946b7332fde42344Tetsuo Handa		return matched_acl->cond->grant_log == TOMOYO_GRANTLOG_YES;
338eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	mode = p->config[index];
339eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (mode == TOMOYO_CONFIG_USE_DEFAULT)
340eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		mode = p->config[category];
341eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (mode == TOMOYO_CONFIG_USE_DEFAULT)
342eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		mode = p->default_config;
343eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (is_granted)
344eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return mode & TOMOYO_CONFIG_WANT_GRANT_LOG;
345eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	return mode & TOMOYO_CONFIG_WANT_REJECT_LOG;
346eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
347eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
348eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
349eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_write_log2 - Write an audit log.
350eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
351eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @r:    Pointer to "struct tomoyo_request_info".
352eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @len:  Buffer size needed for @fmt and @args.
353eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @fmt:  The printf()'s format string.
354eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @args: va_list structure for @fmt.
355eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
356eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns nothing.
357eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
358eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handavoid tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt,
359eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		       va_list args)
360eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
361eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	char *buf;
362eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	struct tomoyo_log *entry;
363eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	bool quota_exceeded = false;
3641f067a682a9bd252107ac6f6946b7332fde42344Tetsuo Handa	if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type,
3651f067a682a9bd252107ac6f6946b7332fde42344Tetsuo Handa			      r->matched_acl, r->granted))
366eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		goto out;
367eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	buf = tomoyo_init_log(r, len, fmt, args);
368eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!buf)
369eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		goto out;
370eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	entry = kzalloc(sizeof(*entry), GFP_NOFS);
371eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!entry) {
372eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		kfree(buf);
373eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		goto out;
374eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	}
375eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	entry->log = buf;
376eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	len = tomoyo_round2(strlen(buf) + 1);
377eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	/*
378eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	 * The entry->size is used for memory quota checks.
379eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	 * Don't go beyond strlen(entry->log).
380eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	 */
381eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	entry->size = len + tomoyo_round2(sizeof(*entry));
382eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	spin_lock(&tomoyo_log_lock);
383eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] &&
384eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	    tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >=
385eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	    tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) {
386eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		quota_exceeded = true;
387eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	} else {
388eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size;
389eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		list_add_tail(&entry->list, &tomoyo_log);
390eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		tomoyo_log_count++;
391eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	}
392eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	spin_unlock(&tomoyo_log_lock);
393eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (quota_exceeded) {
394eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		kfree(buf);
395eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		kfree(entry);
396eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		goto out;
397eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	}
398eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	wake_up(&tomoyo_log_wait);
399eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handaout:
400eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	return;
401eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
402eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
403eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
404eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_write_log - Write an audit log.
405eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
406eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @r:   Pointer to "struct tomoyo_request_info".
407eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @fmt: The printf()'s format string, followed by parameters.
408eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
409eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns nothing.
410eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
411eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handavoid tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...)
412eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
413eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	va_list args;
414eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	int len;
415eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	va_start(args, fmt);
416eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	len = vsnprintf((char *) &len, 1, fmt, args) + 1;
417eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	va_end(args);
418eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	va_start(args, fmt);
419eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	tomoyo_write_log2(r, len, fmt, args);
420eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	va_end(args);
421eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
422eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
423eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
424eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_read_log - Read an audit log.
425eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
426eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @head: Pointer to "struct tomoyo_io_buffer".
427eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
428eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns nothing.
429eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
430eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handavoid tomoyo_read_log(struct tomoyo_io_buffer *head)
431eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
432eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	struct tomoyo_log *ptr = NULL;
433eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (head->r.w_pos)
434eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return;
435eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	kfree(head->read_buf);
436eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	head->read_buf = NULL;
437eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	spin_lock(&tomoyo_log_lock);
438eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (!list_empty(&tomoyo_log)) {
439eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		ptr = list_entry(tomoyo_log.next, typeof(*ptr), list);
440eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		list_del(&ptr->list);
441eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		tomoyo_log_count--;
442eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size;
443eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	}
444eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	spin_unlock(&tomoyo_log_lock);
445eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (ptr) {
446eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		head->read_buf = ptr->log;
447eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		head->r.w[head->r.w_pos++] = head->read_buf;
448eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		kfree(ptr);
449eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	}
450eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
451eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa
452eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa/**
453eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * tomoyo_poll_log - Wait for an audit log.
454eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
455eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * @file: Pointer to "struct file".
4566041e8346f2165679c2184cab60db768d6a26a1dTetsuo Handa * @wait: Pointer to "poll_table". Maybe NULL.
457eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa *
458eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa * Returns POLLIN | POLLRDNORM when ready to read an audit log.
459eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa */
4606041e8346f2165679c2184cab60db768d6a26a1dTetsuo Handaunsigned int tomoyo_poll_log(struct file *file, poll_table *wait)
461eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa{
462eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (tomoyo_log_count)
463eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return POLLIN | POLLRDNORM;
464eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	poll_wait(file, &tomoyo_log_wait, wait);
465eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	if (tomoyo_log_count)
466eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa		return POLLIN | POLLRDNORM;
467eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa	return 0;
468eadd99cc85347b4f9eb10122ac90032eb4971b02Tetsuo Handa}
469