| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1 | /* | 
 | 2 |  * security/tomoyo/file.c | 
 | 3 |  * | 
| Tetsuo Handa | c3ef150 | 2010-05-17 10:12:46 +0900 | [diff] [blame] | 4 |  * Pathname restriction functions. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 5 |  * | 
| Tetsuo Handa | c3ef150 | 2010-05-17 10:12:46 +0900 | [diff] [blame] | 6 |  * Copyright (C) 2005-2010  NTT DATA CORPORATION | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 7 |  */ | 
 | 8 |  | 
 | 9 | #include "common.h" | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 10 | #include <linux/slab.h> | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 11 |  | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 12 | /* Keyword array for operations with one pathname. */ | 
| Tetsuo Handa | 71c2823 | 2010-06-16 16:26:38 +0900 | [diff] [blame] | 13 | const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 14 | 	[TOMOYO_TYPE_READ_WRITE] = "read/write", | 
 | 15 | 	[TOMOYO_TYPE_EXECUTE]    = "execute", | 
 | 16 | 	[TOMOYO_TYPE_READ]       = "read", | 
 | 17 | 	[TOMOYO_TYPE_WRITE]      = "write", | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 18 | 	[TOMOYO_TYPE_UNLINK]     = "unlink", | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 19 | 	[TOMOYO_TYPE_RMDIR]      = "rmdir", | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 20 | 	[TOMOYO_TYPE_TRUNCATE]   = "truncate", | 
 | 21 | 	[TOMOYO_TYPE_SYMLINK]    = "symlink", | 
 | 22 | 	[TOMOYO_TYPE_REWRITE]    = "rewrite", | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 23 | 	[TOMOYO_TYPE_CHROOT]     = "chroot", | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 24 | 	[TOMOYO_TYPE_UMOUNT]     = "unmount", | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 25 | }; | 
 | 26 |  | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 27 | /* Keyword array for operations with one pathname and three numbers. */ | 
| Tetsuo Handa | 71c2823 | 2010-06-16 16:26:38 +0900 | [diff] [blame] | 28 | const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = { | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 29 | 	[TOMOYO_TYPE_MKBLOCK]    = "mkblock", | 
 | 30 | 	[TOMOYO_TYPE_MKCHAR]     = "mkchar", | 
 | 31 | }; | 
 | 32 |  | 
 | 33 | /* Keyword array for operations with two pathnames. */ | 
| Tetsuo Handa | 71c2823 | 2010-06-16 16:26:38 +0900 | [diff] [blame] | 34 | const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 35 | 	[TOMOYO_TYPE_LINK]       = "link", | 
 | 36 | 	[TOMOYO_TYPE_RENAME]     = "rename", | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 37 | 	[TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 38 | }; | 
 | 39 |  | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 40 | /* Keyword array for operations with one pathname and one number. */ | 
| Tetsuo Handa | 71c2823 | 2010-06-16 16:26:38 +0900 | [diff] [blame] | 41 | const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 42 | 	[TOMOYO_TYPE_CREATE]     = "create", | 
 | 43 | 	[TOMOYO_TYPE_MKDIR]      = "mkdir", | 
 | 44 | 	[TOMOYO_TYPE_MKFIFO]     = "mkfifo", | 
 | 45 | 	[TOMOYO_TYPE_MKSOCK]     = "mksock", | 
 | 46 | 	[TOMOYO_TYPE_IOCTL]      = "ioctl", | 
 | 47 | 	[TOMOYO_TYPE_CHMOD]      = "chmod", | 
 | 48 | 	[TOMOYO_TYPE_CHOWN]      = "chown", | 
 | 49 | 	[TOMOYO_TYPE_CHGRP]      = "chgrp", | 
 | 50 | }; | 
 | 51 |  | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 52 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | 
 | 53 | 	[TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, | 
 | 54 | 	[TOMOYO_TYPE_EXECUTE]    = TOMOYO_MAC_FILE_EXECUTE, | 
 | 55 | 	[TOMOYO_TYPE_READ]       = TOMOYO_MAC_FILE_OPEN, | 
 | 56 | 	[TOMOYO_TYPE_WRITE]      = TOMOYO_MAC_FILE_OPEN, | 
 | 57 | 	[TOMOYO_TYPE_UNLINK]     = TOMOYO_MAC_FILE_UNLINK, | 
 | 58 | 	[TOMOYO_TYPE_RMDIR]      = TOMOYO_MAC_FILE_RMDIR, | 
 | 59 | 	[TOMOYO_TYPE_TRUNCATE]   = TOMOYO_MAC_FILE_TRUNCATE, | 
 | 60 | 	[TOMOYO_TYPE_SYMLINK]    = TOMOYO_MAC_FILE_SYMLINK, | 
 | 61 | 	[TOMOYO_TYPE_REWRITE]    = TOMOYO_MAC_FILE_REWRITE, | 
 | 62 | 	[TOMOYO_TYPE_CHROOT]     = TOMOYO_MAC_FILE_CHROOT, | 
 | 63 | 	[TOMOYO_TYPE_UMOUNT]     = TOMOYO_MAC_FILE_UMOUNT, | 
 | 64 | }; | 
 | 65 |  | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 66 | static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 67 | 	[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, | 
 | 68 | 	[TOMOYO_TYPE_MKCHAR]  = TOMOYO_MAC_FILE_MKCHAR, | 
 | 69 | }; | 
 | 70 |  | 
 | 71 | static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { | 
 | 72 | 	[TOMOYO_TYPE_LINK]       = TOMOYO_MAC_FILE_LINK, | 
 | 73 | 	[TOMOYO_TYPE_RENAME]     = TOMOYO_MAC_FILE_RENAME, | 
 | 74 | 	[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, | 
 | 75 | }; | 
 | 76 |  | 
 | 77 | static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | 
 | 78 | 	[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, | 
 | 79 | 	[TOMOYO_TYPE_MKDIR]  = TOMOYO_MAC_FILE_MKDIR, | 
 | 80 | 	[TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, | 
 | 81 | 	[TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, | 
 | 82 | 	[TOMOYO_TYPE_IOCTL]  = TOMOYO_MAC_FILE_IOCTL, | 
 | 83 | 	[TOMOYO_TYPE_CHMOD]  = TOMOYO_MAC_FILE_CHMOD, | 
 | 84 | 	[TOMOYO_TYPE_CHOWN]  = TOMOYO_MAC_FILE_CHOWN, | 
 | 85 | 	[TOMOYO_TYPE_CHGRP]  = TOMOYO_MAC_FILE_CHGRP, | 
 | 86 | }; | 
 | 87 |  | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 88 | void tomoyo_put_name_union(struct tomoyo_name_union *ptr) | 
 | 89 | { | 
 | 90 | 	if (!ptr) | 
 | 91 | 		return; | 
 | 92 | 	if (ptr->is_group) | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 93 | 		tomoyo_put_group(ptr->group); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 94 | 	else | 
 | 95 | 		tomoyo_put_name(ptr->filename); | 
 | 96 | } | 
 | 97 |  | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 98 | const struct tomoyo_path_info * | 
 | 99 | tomoyo_compare_name_union(const struct tomoyo_path_info *name, | 
 | 100 | 			  const struct tomoyo_name_union *ptr) | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 101 | { | 
 | 102 | 	if (ptr->is_group) | 
| Tetsuo Handa | 3f62963 | 2010-06-03 20:37:26 +0900 | [diff] [blame] | 103 | 		return tomoyo_path_matches_group(name, ptr->group); | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 104 | 	if (tomoyo_path_matches_pattern(name, ptr->filename)) | 
 | 105 | 		return ptr->filename; | 
 | 106 | 	return NULL; | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 107 | } | 
 | 108 |  | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 109 | void tomoyo_put_number_union(struct tomoyo_number_union *ptr) | 
 | 110 | { | 
 | 111 | 	if (ptr && ptr->is_group) | 
| Tetsuo Handa | a98aa4d | 2010-06-17 16:52:29 +0900 | [diff] [blame] | 112 | 		tomoyo_put_group(ptr->group); | 
| Tetsuo Handa | 4c3e9e2 | 2010-05-17 10:06:58 +0900 | [diff] [blame] | 113 | } | 
 | 114 |  | 
 | 115 | bool tomoyo_compare_number_union(const unsigned long value, | 
 | 116 | 				 const struct tomoyo_number_union *ptr) | 
 | 117 | { | 
 | 118 | 	if (ptr->is_group) | 
 | 119 | 		return tomoyo_number_matches_group(value, value, ptr->group); | 
 | 120 | 	return value >= ptr->values[0] && value <= ptr->values[1]; | 
 | 121 | } | 
 | 122 |  | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 123 | static void tomoyo_add_slash(struct tomoyo_path_info *buf) | 
 | 124 | { | 
 | 125 | 	if (buf->is_dir) | 
 | 126 | 		return; | 
 | 127 | 	/* | 
 | 128 | 	 * This is OK because tomoyo_encode() reserves space for appending "/". | 
 | 129 | 	 */ | 
 | 130 | 	strcat((char *) buf->name, "/"); | 
 | 131 | 	tomoyo_fill_path_info(buf); | 
 | 132 | } | 
 | 133 |  | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 134 | /** | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 135 |  * tomoyo_strendswith - Check whether the token ends with the given token. | 
 | 136 |  * | 
 | 137 |  * @name: The token to check. | 
 | 138 |  * @tail: The token to find. | 
 | 139 |  * | 
 | 140 |  * Returns true if @name ends with @tail, false otherwise. | 
 | 141 |  */ | 
 | 142 | static bool tomoyo_strendswith(const char *name, const char *tail) | 
 | 143 | { | 
 | 144 | 	int len; | 
 | 145 |  | 
 | 146 | 	if (!name || !tail) | 
 | 147 | 		return false; | 
 | 148 | 	len = strlen(name) - strlen(tail); | 
 | 149 | 	return len >= 0 && !strcmp(name + len, tail); | 
 | 150 | } | 
 | 151 |  | 
 | 152 | /** | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 153 |  * tomoyo_get_realpath - Get realpath. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 154 |  * | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 155 |  * @buf:  Pointer to "struct tomoyo_path_info". | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 156 |  * @path: Pointer to "struct path". | 
 | 157 |  * | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 158 |  * Returns true on success, false otherwise. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 159 |  */ | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 160 | static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 161 | { | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 162 | 	buf->name = tomoyo_realpath_from_path(path); | 
 | 163 | 	if (buf->name) { | 
 | 164 | 		tomoyo_fill_path_info(buf); | 
 | 165 | 		return true; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 166 | 	} | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 167 |         return false; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 168 | } | 
 | 169 |  | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 170 | /** | 
 | 171 |  * tomoyo_audit_path_log - Audit path request log. | 
 | 172 |  * | 
 | 173 |  * @r: Pointer to "struct tomoyo_request_info". | 
 | 174 |  * | 
 | 175 |  * Returns 0 on success, negative value otherwise. | 
 | 176 |  */ | 
 | 177 | static int tomoyo_audit_path_log(struct tomoyo_request_info *r) | 
 | 178 | { | 
 | 179 | 	const char *operation = tomoyo_path_keyword[r->param.path.operation]; | 
 | 180 | 	const struct tomoyo_path_info *filename = r->param.path.filename; | 
 | 181 | 	if (r->granted) | 
 | 182 | 		return 0; | 
 | 183 | 	tomoyo_warn_log(r, "%s %s", operation, filename->name); | 
 | 184 | 	return tomoyo_supervisor(r, "allow_%s %s\n", operation, | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 185 | 				 tomoyo_pattern(filename)); | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 186 | } | 
 | 187 |  | 
 | 188 | /** | 
 | 189 |  * tomoyo_audit_path2_log - Audit path/path request log. | 
 | 190 |  * | 
 | 191 |  * @r: Pointer to "struct tomoyo_request_info". | 
 | 192 |  * | 
 | 193 |  * Returns 0 on success, negative value otherwise. | 
 | 194 |  */ | 
 | 195 | static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) | 
 | 196 | { | 
 | 197 | 	const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; | 
 | 198 | 	const struct tomoyo_path_info *filename1 = r->param.path2.filename1; | 
 | 199 | 	const struct tomoyo_path_info *filename2 = r->param.path2.filename2; | 
 | 200 | 	if (r->granted) | 
 | 201 | 		return 0; | 
 | 202 | 	tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, | 
 | 203 | 			filename2->name); | 
 | 204 | 	return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 205 | 				 tomoyo_pattern(filename1), | 
 | 206 | 				 tomoyo_pattern(filename2)); | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 207 | } | 
 | 208 |  | 
 | 209 | /** | 
 | 210 |  * tomoyo_audit_mkdev_log - Audit path/number/number/number request log. | 
 | 211 |  * | 
 | 212 |  * @r: Pointer to "struct tomoyo_request_info". | 
 | 213 |  * | 
 | 214 |  * Returns 0 on success, negative value otherwise. | 
 | 215 |  */ | 
 | 216 | static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) | 
 | 217 | { | 
| Tetsuo Handa | 71c2823 | 2010-06-16 16:26:38 +0900 | [diff] [blame] | 218 | 	const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation]; | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 219 | 	const struct tomoyo_path_info *filename = r->param.mkdev.filename; | 
 | 220 | 	const unsigned int major = r->param.mkdev.major; | 
 | 221 | 	const unsigned int minor = r->param.mkdev.minor; | 
 | 222 | 	const unsigned int mode = r->param.mkdev.mode; | 
 | 223 | 	if (r->granted) | 
 | 224 | 		return 0; | 
 | 225 | 	tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, | 
 | 226 | 			major, minor); | 
 | 227 | 	return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 228 | 				 tomoyo_pattern(filename), mode, major, minor); | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 229 | } | 
 | 230 |  | 
 | 231 | /** | 
 | 232 |  * tomoyo_audit_path_number_log - Audit path/number request log. | 
 | 233 |  * | 
 | 234 |  * @r:     Pointer to "struct tomoyo_request_info". | 
 | 235 |  * @error: Error code. | 
 | 236 |  * | 
 | 237 |  * Returns 0 on success, negative value otherwise. | 
 | 238 |  */ | 
 | 239 | static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | 
 | 240 | { | 
 | 241 | 	const u8 type = r->param.path_number.operation; | 
 | 242 | 	u8 radix; | 
 | 243 | 	const struct tomoyo_path_info *filename = r->param.path_number.filename; | 
 | 244 | 	const char *operation = tomoyo_path_number_keyword[type]; | 
 | 245 | 	char buffer[64]; | 
 | 246 | 	if (r->granted) | 
 | 247 | 		return 0; | 
 | 248 | 	switch (type) { | 
 | 249 | 	case TOMOYO_TYPE_CREATE: | 
 | 250 | 	case TOMOYO_TYPE_MKDIR: | 
 | 251 | 	case TOMOYO_TYPE_MKFIFO: | 
 | 252 | 	case TOMOYO_TYPE_MKSOCK: | 
 | 253 | 	case TOMOYO_TYPE_CHMOD: | 
 | 254 | 		radix = TOMOYO_VALUE_TYPE_OCTAL; | 
 | 255 | 		break; | 
 | 256 | 	case TOMOYO_TYPE_IOCTL: | 
 | 257 | 		radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; | 
 | 258 | 		break; | 
 | 259 | 	default: | 
 | 260 | 		radix = TOMOYO_VALUE_TYPE_DECIMAL; | 
 | 261 | 		break; | 
 | 262 | 	} | 
 | 263 | 	tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, | 
 | 264 | 			   radix); | 
 | 265 | 	tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); | 
 | 266 | 	return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 267 | 				 tomoyo_pattern(filename), buffer); | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 268 | } | 
 | 269 |  | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 270 | static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, | 
 | 271 | 					  const struct tomoyo_acl_head *b) | 
 | 272 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 273 | 	return container_of(a, struct tomoyo_readable_file, | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 274 | 			    head)->filename == | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 275 | 		container_of(b, struct tomoyo_readable_file, | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 276 | 			     head)->filename; | 
 | 277 | } | 
 | 278 |  | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 279 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 280 |  * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 281 |  * | 
 | 282 |  * @filename:  Filename unconditionally permitted to open() for reading. | 
 | 283 |  * @is_delete: True if it is a delete request. | 
 | 284 |  * | 
 | 285 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 286 |  * | 
 | 287 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 288 |  */ | 
 | 289 | static int tomoyo_update_globally_readable_entry(const char *filename, | 
 | 290 | 						 const bool is_delete) | 
 | 291 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 292 | 	struct tomoyo_readable_file e = { }; | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 293 | 	int error; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 294 |  | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 295 | 	if (!tomoyo_correct_word(filename)) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 296 | 		return -EINVAL; | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 297 | 	e.filename = tomoyo_get_name(filename); | 
 | 298 | 	if (!e.filename) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 299 | 		return -ENOMEM; | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 300 | 	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 301 | 				     &tomoyo_policy_list | 
 | 302 | 				     [TOMOYO_ID_GLOBALLY_READABLE], | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 303 | 				     tomoyo_same_globally_readable); | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 304 | 	tomoyo_put_name(e.filename); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 305 | 	return error; | 
 | 306 | } | 
 | 307 |  | 
 | 308 | /** | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 309 |  * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 310 |  * | 
 | 311 |  * @filename: The filename to check. | 
 | 312 |  * | 
 | 313 |  * Returns true if any domain can open @filename for reading, false otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 314 |  * | 
 | 315 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 316 |  */ | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 317 | static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 318 | 					     filename) | 
 | 319 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 320 | 	struct tomoyo_readable_file *ptr; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 321 | 	bool found = false; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 322 |  | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 323 | 	list_for_each_entry_rcu(ptr, &tomoyo_policy_list | 
 | 324 | 				[TOMOYO_ID_GLOBALLY_READABLE], head.list) { | 
| Tetsuo Handa | 82e0f00 | 2010-06-15 09:22:42 +0900 | [diff] [blame] | 325 | 		if (!ptr->head.is_deleted && | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 326 | 		    tomoyo_path_matches_pattern(filename, ptr->filename)) { | 
 | 327 | 			found = true; | 
 | 328 | 			break; | 
 | 329 | 		} | 
 | 330 | 	} | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 331 | 	return found; | 
 | 332 | } | 
 | 333 |  | 
 | 334 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 335 |  * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 336 |  * | 
 | 337 |  * @data:      String to parse. | 
 | 338 |  * @is_delete: True if it is a delete request. | 
 | 339 |  * | 
 | 340 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 341 |  * | 
 | 342 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 343 |  */ | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 344 | int tomoyo_write_globally_readable(char *data, const bool is_delete) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 345 | { | 
 | 346 | 	return tomoyo_update_globally_readable_entry(data, is_delete); | 
 | 347 | } | 
 | 348 |  | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 349 | static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, | 
 | 350 | 				const struct tomoyo_acl_head *b) | 
 | 351 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 352 | 	return container_of(a, struct tomoyo_no_pattern, head)->pattern == | 
 | 353 | 		container_of(b, struct tomoyo_no_pattern, head)->pattern; | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 354 | } | 
 | 355 |  | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 356 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 357 |  * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 358 |  * | 
 | 359 |  * @pattern:   Pathname pattern. | 
 | 360 |  * @is_delete: True if it is a delete request. | 
 | 361 |  * | 
 | 362 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 363 |  * | 
 | 364 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 365 |  */ | 
 | 366 | static int tomoyo_update_file_pattern_entry(const char *pattern, | 
 | 367 | 					    const bool is_delete) | 
 | 368 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 369 | 	struct tomoyo_no_pattern e = { }; | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 370 | 	int error; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 371 |  | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 372 | 	if (!tomoyo_correct_word(pattern)) | 
| Tetsuo Handa | 3f62963 | 2010-06-03 20:37:26 +0900 | [diff] [blame] | 373 | 		return -EINVAL; | 
 | 374 | 	e.pattern = tomoyo_get_name(pattern); | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 375 | 	if (!e.pattern) | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 376 | 		return -ENOMEM; | 
 | 377 | 	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 378 | 				     &tomoyo_policy_list[TOMOYO_ID_PATTERN], | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 379 | 				     tomoyo_same_pattern); | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 380 | 	tomoyo_put_name(e.pattern); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 381 | 	return error; | 
 | 382 | } | 
 | 383 |  | 
 | 384 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 385 |  * tomoyo_pattern - Get patterned pathname. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 386 |  * | 
 | 387 |  * @filename: The filename to find patterned pathname. | 
 | 388 |  * | 
 | 389 |  * Returns pointer to pathname pattern if matched, @filename otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 390 |  * | 
 | 391 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 392 |  */ | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 393 | const char *tomoyo_pattern(const struct tomoyo_path_info *filename) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 394 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 395 | 	struct tomoyo_no_pattern *ptr; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 396 | 	const struct tomoyo_path_info *pattern = NULL; | 
 | 397 |  | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 398 | 	list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN], | 
 | 399 | 				head.list) { | 
| Tetsuo Handa | 82e0f00 | 2010-06-15 09:22:42 +0900 | [diff] [blame] | 400 | 		if (ptr->head.is_deleted) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 401 | 			continue; | 
 | 402 | 		if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 
 | 403 | 			continue; | 
 | 404 | 		pattern = ptr->pattern; | 
 | 405 | 		if (tomoyo_strendswith(pattern->name, "/\\*")) { | 
 | 406 | 			/* Do nothing. Try to find the better match. */ | 
 | 407 | 		} else { | 
 | 408 | 			/* This would be the better match. Use this. */ | 
 | 409 | 			break; | 
 | 410 | 		} | 
 | 411 | 	} | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 412 | 	if (pattern) | 
 | 413 | 		filename = pattern; | 
| Tetsuo Handa | 17fcfbd | 2010-05-17 10:11:36 +0900 | [diff] [blame] | 414 | 	return filename->name; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 415 | } | 
 | 416 |  | 
 | 417 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 418 |  * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 419 |  * | 
 | 420 |  * @data:      String to parse. | 
 | 421 |  * @is_delete: True if it is a delete request. | 
 | 422 |  * | 
 | 423 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 424 |  * | 
 | 425 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 426 |  */ | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 427 | int tomoyo_write_pattern(char *data, const bool is_delete) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 428 | { | 
 | 429 | 	return tomoyo_update_file_pattern_entry(data, is_delete); | 
 | 430 | } | 
 | 431 |  | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 432 | static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, | 
 | 433 | 				   const struct tomoyo_acl_head *b) | 
 | 434 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 435 | 	return container_of(a, struct tomoyo_no_rewrite, head)->pattern | 
 | 436 | 		== container_of(b, struct tomoyo_no_rewrite, head) | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 437 | 		->pattern; | 
 | 438 | } | 
 | 439 |  | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 440 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 441 |  * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 442 |  * | 
 | 443 |  * @pattern:   Pathname pattern that are not rewritable by default. | 
 | 444 |  * @is_delete: True if it is a delete request. | 
 | 445 |  * | 
 | 446 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 447 |  * | 
 | 448 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 449 |  */ | 
 | 450 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | 
 | 451 | 					  const bool is_delete) | 
 | 452 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 453 | 	struct tomoyo_no_rewrite e = { }; | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 454 | 	int error; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 455 |  | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 456 | 	if (!tomoyo_correct_word(pattern)) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 457 | 		return -EINVAL; | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 458 | 	e.pattern = tomoyo_get_name(pattern); | 
 | 459 | 	if (!e.pattern) | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 460 | 		return -ENOMEM; | 
 | 461 | 	error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 462 | 				     &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], | 
| Tetsuo Handa | 36f5e1f | 2010-06-15 09:23:26 +0900 | [diff] [blame] | 463 | 				     tomoyo_same_no_rewrite); | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 464 | 	tomoyo_put_name(e.pattern); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 465 | 	return error; | 
 | 466 | } | 
 | 467 |  | 
 | 468 | /** | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 469 |  * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 470 |  * | 
 | 471 |  * @filename: Filename to check. | 
 | 472 |  * | 
 | 473 |  * Returns true if @filename is specified by "deny_rewrite" directive, | 
 | 474 |  * false otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 475 |  * | 
 | 476 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 477 |  */ | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 478 | static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 479 | { | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 480 | 	struct tomoyo_no_rewrite *ptr; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 481 | 	bool found = false; | 
 | 482 |  | 
| Tetsuo Handa | a230f9e | 2010-06-17 16:53:24 +0900 | [diff] [blame] | 483 | 	list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], | 
 | 484 | 				head.list) { | 
| Tetsuo Handa | 82e0f00 | 2010-06-15 09:22:42 +0900 | [diff] [blame] | 485 | 		if (ptr->head.is_deleted) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 486 | 			continue; | 
 | 487 | 		if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 
 | 488 | 			continue; | 
 | 489 | 		found = true; | 
 | 490 | 		break; | 
 | 491 | 	} | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 492 | 	return found; | 
 | 493 | } | 
 | 494 |  | 
 | 495 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 496 |  * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 497 |  * | 
 | 498 |  * @data:      String to parse. | 
 | 499 |  * @is_delete: True if it is a delete request. | 
 | 500 |  * | 
 | 501 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 502 |  * | 
 | 503 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 504 |  */ | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 505 | int tomoyo_write_no_rewrite(char *data, const bool is_delete) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 506 | { | 
 | 507 | 	return tomoyo_update_no_rewrite_entry(data, is_delete); | 
 | 508 | } | 
 | 509 |  | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 510 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 511 | 				  const struct tomoyo_acl_info *ptr) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 512 | { | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 513 | 	const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), | 
 | 514 | 							 head); | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 515 | 	if (acl->perm & (1 << r->param.path.operation)) { | 
 | 516 | 		r->param.path.matched_path = | 
 | 517 | 			tomoyo_compare_name_union(r->param.path.filename, | 
 | 518 | 						  &acl->name); | 
 | 519 | 		return r->param.path.matched_path != NULL; | 
 | 520 | 	} | 
 | 521 | 	return false; | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 522 | } | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 523 |  | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 524 | static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 525 | 					 const struct tomoyo_acl_info *ptr) | 
 | 526 | { | 
 | 527 | 	const struct tomoyo_path_number_acl *acl = | 
 | 528 | 		container_of(ptr, typeof(*acl), head); | 
 | 529 | 	return (acl->perm & (1 << r->param.path_number.operation)) && | 
 | 530 | 		tomoyo_compare_number_union(r->param.path_number.number, | 
 | 531 | 					    &acl->number) && | 
 | 532 | 		tomoyo_compare_name_union(r->param.path_number.filename, | 
 | 533 | 					  &acl->name); | 
 | 534 | } | 
 | 535 |  | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 536 | static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 537 | 				   const struct tomoyo_acl_info *ptr) | 
 | 538 | { | 
 | 539 | 	const struct tomoyo_path2_acl *acl = | 
 | 540 | 		container_of(ptr, typeof(*acl), head); | 
 | 541 | 	return (acl->perm & (1 << r->param.path2.operation)) && | 
 | 542 | 		tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) | 
 | 543 | 		&& tomoyo_compare_name_union(r->param.path2.filename2, | 
 | 544 | 					     &acl->name2); | 
 | 545 | } | 
 | 546 |  | 
| Tetsuo Handa | 484ca79 | 2010-07-29 14:29:55 +0900 | [diff] [blame] | 547 | static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 548 | 				const struct tomoyo_acl_info *ptr) | 
 | 549 | { | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 550 | 	const struct tomoyo_mkdev_acl *acl = | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 551 | 		container_of(ptr, typeof(*acl), head); | 
 | 552 | 	return (acl->perm & (1 << r->param.mkdev.operation)) && | 
 | 553 | 		tomoyo_compare_number_union(r->param.mkdev.mode, | 
 | 554 | 					    &acl->mode) && | 
 | 555 | 		tomoyo_compare_number_union(r->param.mkdev.major, | 
 | 556 | 					    &acl->major) && | 
 | 557 | 		tomoyo_compare_number_union(r->param.mkdev.minor, | 
 | 558 | 					    &acl->minor) && | 
 | 559 | 		tomoyo_compare_name_union(r->param.mkdev.filename, | 
 | 560 | 					  &acl->name); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 561 | } | 
 | 562 |  | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 563 | static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, | 
 | 564 | 				 const struct tomoyo_acl_info *b) | 
 | 565 | { | 
 | 566 | 	const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); | 
 | 567 | 	const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 568 | 	return tomoyo_same_acl_head(&p1->head, &p2->head) && | 
 | 569 | 		tomoyo_same_name_union(&p1->name, &p2->name); | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 570 | } | 
 | 571 |  | 
 | 572 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | 
 | 573 | 				  struct tomoyo_acl_info *b, | 
 | 574 | 				  const bool is_delete) | 
 | 575 | { | 
 | 576 | 	u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) | 
 | 577 | 		->perm; | 
 | 578 | 	u16 perm = *a_perm; | 
 | 579 | 	const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; | 
 | 580 | 	if (is_delete) { | 
 | 581 | 		perm &= ~b_perm; | 
 | 582 | 		if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) | 
 | 583 | 			perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); | 
 | 584 | 		else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE))) | 
 | 585 | 			perm &= ~TOMOYO_RW_MASK; | 
 | 586 | 	} else { | 
 | 587 | 		perm |= b_perm; | 
 | 588 | 		if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK) | 
 | 589 | 			perm |= (1 << TOMOYO_TYPE_READ_WRITE); | 
 | 590 | 		else if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) | 
 | 591 | 			perm |= TOMOYO_RW_MASK; | 
 | 592 | 	} | 
 | 593 | 	*a_perm = perm; | 
 | 594 | 	return !perm; | 
 | 595 | } | 
 | 596 |  | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 597 | /** | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 598 |  * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 599 |  * | 
 | 600 |  * @type:      Type of operation. | 
 | 601 |  * @filename:  Filename. | 
 | 602 |  * @domain:    Pointer to "struct tomoyo_domain_info". | 
 | 603 |  * @is_delete: True if it is a delete request. | 
 | 604 |  * | 
 | 605 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 606 |  * | 
 | 607 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 608 |  */ | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 609 | static int tomoyo_update_path_acl(const u8 type, const char *filename, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 610 | 				  struct tomoyo_domain_info * const domain, | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 611 | 				  const bool is_delete) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 612 | { | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 613 | 	struct tomoyo_path_acl e = { | 
 | 614 | 		.head.type = TOMOYO_TYPE_PATH_ACL, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 615 | 		.perm = 1 << type | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 616 | 	}; | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 617 | 	int error; | 
 | 618 | 	if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) | 
 | 619 | 		e.perm |= TOMOYO_RW_MASK; | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 620 | 	if (!tomoyo_parse_name_union(filename, &e.name)) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 621 | 		return -EINVAL; | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 622 | 	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 
 | 623 | 				     tomoyo_same_path_acl, | 
 | 624 | 				     tomoyo_merge_path_acl); | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 625 | 	tomoyo_put_name_union(&e.name); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 626 | 	return error; | 
 | 627 | } | 
 | 628 |  | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 629 | static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 630 | 					 const struct tomoyo_acl_info *b) | 
 | 631 | { | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 632 | 	const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 633 | 								head); | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 634 | 	const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 635 | 								head); | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 636 | 	return tomoyo_same_acl_head(&p1->head, &p2->head) | 
 | 637 | 		&& tomoyo_same_name_union(&p1->name, &p2->name) | 
 | 638 | 		&& tomoyo_same_number_union(&p1->mode, &p2->mode) | 
 | 639 | 		&& tomoyo_same_number_union(&p1->major, &p2->major) | 
 | 640 | 		&& tomoyo_same_number_union(&p1->minor, &p2->minor); | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 641 | } | 
 | 642 |  | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 643 | static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 644 | 					  struct tomoyo_acl_info *b, | 
 | 645 | 					  const bool is_delete) | 
 | 646 | { | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 647 | 	u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 648 | 					 head)->perm; | 
 | 649 | 	u8 perm = *a_perm; | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 650 | 	const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 651 | 		->perm; | 
 | 652 | 	if (is_delete) | 
 | 653 | 		perm &= ~b_perm; | 
 | 654 | 	else | 
 | 655 | 		perm |= b_perm; | 
 | 656 | 	*a_perm = perm; | 
 | 657 | 	return !perm; | 
 | 658 | } | 
 | 659 |  | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 660 | /** | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 661 |  * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 662 |  * | 
 | 663 |  * @type:      Type of operation. | 
 | 664 |  * @filename:  Filename. | 
 | 665 |  * @mode:      Create mode. | 
 | 666 |  * @major:     Device major number. | 
 | 667 |  * @minor:     Device minor number. | 
 | 668 |  * @domain:    Pointer to "struct tomoyo_domain_info". | 
 | 669 |  * @is_delete: True if it is a delete request. | 
 | 670 |  * | 
 | 671 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 672 |  * | 
 | 673 |  * Caller holds tomoyo_read_lock(). | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 674 |  */ | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 675 | static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 676 | 					  char *mode, char *major, char *minor, | 
 | 677 | 					  struct tomoyo_domain_info * const | 
 | 678 | 					  domain, const bool is_delete) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 679 | { | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 680 | 	struct tomoyo_mkdev_acl e = { | 
 | 681 | 		.head.type = TOMOYO_TYPE_MKDEV_ACL, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 682 | 		.perm = 1 << type | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 683 | 	}; | 
 | 684 | 	int error = is_delete ? -ENOENT : -ENOMEM; | 
 | 685 | 	if (!tomoyo_parse_name_union(filename, &e.name) || | 
 | 686 | 	    !tomoyo_parse_number_union(mode, &e.mode) || | 
 | 687 | 	    !tomoyo_parse_number_union(major, &e.major) || | 
 | 688 | 	    !tomoyo_parse_number_union(minor, &e.minor)) | 
 | 689 | 		goto out; | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 690 | 	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 691 | 				     tomoyo_same_mkdev_acl, | 
 | 692 | 				     tomoyo_merge_mkdev_acl); | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 693 |  out: | 
 | 694 | 	tomoyo_put_name_union(&e.name); | 
 | 695 | 	tomoyo_put_number_union(&e.mode); | 
 | 696 | 	tomoyo_put_number_union(&e.major); | 
 | 697 | 	tomoyo_put_number_union(&e.minor); | 
 | 698 | 	return error; | 
 | 699 | } | 
 | 700 |  | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 701 | static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, | 
 | 702 | 				  const struct tomoyo_acl_info *b) | 
 | 703 | { | 
 | 704 | 	const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); | 
 | 705 | 	const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 706 | 	return tomoyo_same_acl_head(&p1->head, &p2->head) | 
 | 707 | 		&& tomoyo_same_name_union(&p1->name1, &p2->name1) | 
 | 708 | 		&& tomoyo_same_name_union(&p1->name2, &p2->name2); | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 709 | } | 
 | 710 |  | 
 | 711 | static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, | 
 | 712 | 				   struct tomoyo_acl_info *b, | 
 | 713 | 				   const bool is_delete) | 
 | 714 | { | 
 | 715 | 	u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) | 
 | 716 | 		->perm; | 
 | 717 | 	u8 perm = *a_perm; | 
 | 718 | 	const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; | 
 | 719 | 	if (is_delete) | 
 | 720 | 		perm &= ~b_perm; | 
 | 721 | 	else | 
 | 722 | 		perm |= b_perm; | 
 | 723 | 	*a_perm = perm; | 
 | 724 | 	return !perm; | 
 | 725 | } | 
 | 726 |  | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 727 | /** | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 728 |  * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 729 |  * | 
 | 730 |  * @type:      Type of operation. | 
 | 731 |  * @filename1: First filename. | 
 | 732 |  * @filename2: Second filename. | 
 | 733 |  * @domain:    Pointer to "struct tomoyo_domain_info". | 
 | 734 |  * @is_delete: True if it is a delete request. | 
 | 735 |  * | 
 | 736 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 737 |  * | 
 | 738 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 739 |  */ | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 740 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, | 
 | 741 | 				   const char *filename2, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 742 | 				   struct tomoyo_domain_info * const domain, | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 743 | 				   const bool is_delete) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 744 | { | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 745 | 	struct tomoyo_path2_acl e = { | 
 | 746 | 		.head.type = TOMOYO_TYPE_PATH2_ACL, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 747 | 		.perm = 1 << type | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 748 | 	}; | 
| Tetsuo Handa | 9e4b50e | 2010-05-06 12:40:02 +0900 | [diff] [blame] | 749 | 	int error = is_delete ? -ENOENT : -ENOMEM; | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 750 | 	if (!tomoyo_parse_name_union(filename1, &e.name1) || | 
 | 751 | 	    !tomoyo_parse_name_union(filename2, &e.name2)) | 
| Tetsuo Handa | ca0b7df | 2010-02-07 20:23:59 +0900 | [diff] [blame] | 752 | 		goto out; | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 753 | 	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 
 | 754 | 				     tomoyo_same_path2_acl, | 
 | 755 | 				     tomoyo_merge_path2_acl); | 
| Tetsuo Handa | ca0b7df | 2010-02-07 20:23:59 +0900 | [diff] [blame] | 756 |  out: | 
| Tetsuo Handa | 7762fbf | 2010-05-10 17:30:26 +0900 | [diff] [blame] | 757 | 	tomoyo_put_name_union(&e.name1); | 
 | 758 | 	tomoyo_put_name_union(&e.name2); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 759 | 	return error; | 
 | 760 | } | 
 | 761 |  | 
 | 762 | /** | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 763 |  * tomoyo_path_permission - Check permission for single path operation. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 764 |  * | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 765 |  * @r:         Pointer to "struct tomoyo_request_info". | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 766 |  * @operation: Type of operation. | 
 | 767 |  * @filename:  Filename to check. | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 768 |  * | 
 | 769 |  * Returns 0 on success, negative value otherwise. | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 770 |  * | 
 | 771 |  * Caller holds tomoyo_read_lock(). | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 772 |  */ | 
| Tetsuo Handa | 05336de | 2010-06-16 16:20:24 +0900 | [diff] [blame] | 773 | int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | 
 | 774 | 			   const struct tomoyo_path_info *filename) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 775 | { | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 776 | 	int error; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 777 |  | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 778 |  next: | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 779 | 	r->type = tomoyo_p2mac[operation]; | 
 | 780 | 	r->mode = tomoyo_get_mode(r->profile, r->type); | 
 | 781 | 	if (r->mode == TOMOYO_CONFIG_DISABLED) | 
 | 782 | 		return 0; | 
| Tetsuo Handa | cf6e9a6 | 2010-06-16 16:21:36 +0900 | [diff] [blame] | 783 | 	r->param_type = TOMOYO_TYPE_PATH_ACL; | 
 | 784 | 	r->param.path.filename = filename; | 
 | 785 | 	r->param.path.operation = operation; | 
| Tetsuo Handa | 17fcfbd | 2010-05-17 10:11:36 +0900 | [diff] [blame] | 786 | 	do { | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 787 | 		tomoyo_check_acl(r, tomoyo_check_path_acl); | 
 | 788 | 		if (!r->granted && operation == TOMOYO_TYPE_READ && | 
| Tetsuo Handa | 05336de | 2010-06-16 16:20:24 +0900 | [diff] [blame] | 789 | 		    !r->domain->ignore_global_allow_read && | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 790 | 		    tomoyo_globally_readable_file(filename)) | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 791 | 			r->granted = true; | 
 | 792 | 		error = tomoyo_audit_path_log(r); | 
| Tetsuo Handa | 05336de | 2010-06-16 16:20:24 +0900 | [diff] [blame] | 793 | 		/* | 
 | 794 | 		 * Do not retry for execute request, for alias may have | 
 | 795 | 		 * changed. | 
 | 796 | 		 */ | 
 | 797 | 	} while (error == TOMOYO_RETRY_REQUEST && | 
 | 798 | 		 operation != TOMOYO_TYPE_EXECUTE); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 799 | 	/* | 
 | 800 | 	 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, | 
 | 801 | 	 * we need to check "allow_rewrite" permission if the filename is | 
 | 802 | 	 * specified by "deny_rewrite" keyword. | 
 | 803 | 	 */ | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 804 | 	if (!error && operation == TOMOYO_TYPE_TRUNCATE && | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 805 | 	    tomoyo_no_rewrite_file(filename)) { | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 806 | 		operation = TOMOYO_TYPE_REWRITE; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 807 | 		goto next; | 
 | 808 | 	} | 
 | 809 | 	return error; | 
 | 810 | } | 
 | 811 |  | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 812 | static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, | 
 | 813 | 					const struct tomoyo_acl_info *b) | 
 | 814 | { | 
 | 815 | 	const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), | 
 | 816 | 							       head); | 
 | 817 | 	const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), | 
 | 818 | 							       head); | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 819 | 	return tomoyo_same_acl_head(&p1->head, &p2->head) | 
 | 820 | 		&& tomoyo_same_name_union(&p1->name, &p2->name) | 
 | 821 | 		&& tomoyo_same_number_union(&p1->number, &p2->number); | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 822 | } | 
 | 823 |  | 
 | 824 | static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, | 
 | 825 | 					 struct tomoyo_acl_info *b, | 
 | 826 | 					 const bool is_delete) | 
 | 827 | { | 
 | 828 | 	u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, | 
 | 829 | 					  head)->perm; | 
 | 830 | 	u8 perm = *a_perm; | 
 | 831 | 	const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) | 
 | 832 | 		->perm; | 
 | 833 | 	if (is_delete) | 
 | 834 | 		perm &= ~b_perm; | 
 | 835 | 	else | 
 | 836 | 		perm |= b_perm; | 
 | 837 | 	*a_perm = perm; | 
 | 838 | 	return !perm; | 
 | 839 | } | 
 | 840 |  | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 841 | /** | 
 | 842 |  * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. | 
 | 843 |  * | 
 | 844 |  * @type:      Type of operation. | 
 | 845 |  * @filename:  Filename. | 
 | 846 |  * @number:    Number. | 
 | 847 |  * @domain:    Pointer to "struct tomoyo_domain_info". | 
 | 848 |  * @is_delete: True if it is a delete request. | 
 | 849 |  * | 
 | 850 |  * Returns 0 on success, negative value otherwise. | 
 | 851 |  */ | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 852 | static int tomoyo_update_path_number_acl(const u8 type, const char *filename, | 
 | 853 | 					 char *number, | 
 | 854 | 					 struct tomoyo_domain_info * const | 
 | 855 | 					 domain, | 
 | 856 | 					 const bool is_delete) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 857 | { | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 858 | 	struct tomoyo_path_number_acl e = { | 
 | 859 | 		.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 860 | 		.perm = 1 << type | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 861 | 	}; | 
 | 862 | 	int error = is_delete ? -ENOENT : -ENOMEM; | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 863 | 	if (!tomoyo_parse_name_union(filename, &e.name)) | 
 | 864 | 		return -EINVAL; | 
 | 865 | 	if (!tomoyo_parse_number_union(number, &e.number)) | 
 | 866 | 		goto out; | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 867 | 	error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 
 | 868 | 				     tomoyo_same_path_number_acl, | 
 | 869 | 				     tomoyo_merge_path_number_acl); | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 870 |  out: | 
 | 871 | 	tomoyo_put_name_union(&e.name); | 
 | 872 | 	tomoyo_put_number_union(&e.number); | 
 | 873 | 	return error; | 
 | 874 | } | 
 | 875 |  | 
 | 876 | /** | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 877 |  * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". | 
 | 878 |  * | 
 | 879 |  * @type:   Type of operation. | 
 | 880 |  * @path:   Pointer to "struct path". | 
 | 881 |  * @number: Number. | 
 | 882 |  * | 
 | 883 |  * Returns 0 on success, negative value otherwise. | 
 | 884 |  */ | 
 | 885 | int tomoyo_path_number_perm(const u8 type, struct path *path, | 
 | 886 | 			    unsigned long number) | 
 | 887 | { | 
 | 888 | 	struct tomoyo_request_info r; | 
 | 889 | 	int error = -ENOMEM; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 890 | 	struct tomoyo_path_info buf; | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 891 | 	int idx; | 
 | 892 |  | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 893 | 	if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) | 
 | 894 | 	    == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 895 | 		return 0; | 
 | 896 | 	idx = tomoyo_read_lock(); | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 897 | 	if (!tomoyo_get_realpath(&buf, path)) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 898 | 		goto out; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 899 | 	if (type == TOMOYO_TYPE_MKDIR) | 
 | 900 | 		tomoyo_add_slash(&buf); | 
| Tetsuo Handa | cb917cf | 2010-06-16 16:28:21 +0900 | [diff] [blame] | 901 | 	r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; | 
 | 902 | 	r.param.path_number.operation = type; | 
 | 903 | 	r.param.path_number.filename = &buf; | 
 | 904 | 	r.param.path_number.number = number; | 
 | 905 | 	do { | 
 | 906 | 		tomoyo_check_acl(&r, tomoyo_check_path_number_acl); | 
 | 907 | 		error = tomoyo_audit_path_number_log(&r); | 
 | 908 | 	} while (error == TOMOYO_RETRY_REQUEST); | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 909 | 	kfree(buf.name); | 
| Tetsuo Handa | cb917cf | 2010-06-16 16:28:21 +0900 | [diff] [blame] | 910 |  out: | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 911 | 	tomoyo_read_unlock(idx); | 
 | 912 | 	if (r.mode != TOMOYO_CONFIG_ENFORCING) | 
 | 913 | 		error = 0; | 
 | 914 | 	return error; | 
 | 915 | } | 
 | 916 |  | 
 | 917 | /** | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 918 |  * tomoyo_check_open_permission - Check permission for "read" and "write". | 
 | 919 |  * | 
 | 920 |  * @domain: Pointer to "struct tomoyo_domain_info". | 
 | 921 |  * @path:   Pointer to "struct path". | 
 | 922 |  * @flag:   Flags for open(). | 
 | 923 |  * | 
 | 924 |  * Returns 0 on success, negative value otherwise. | 
 | 925 |  */ | 
 | 926 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | 
 | 927 | 				 struct path *path, const int flag) | 
 | 928 | { | 
 | 929 | 	const u8 acc_mode = ACC_MODE(flag); | 
| Tetsuo Handa | eae61f3 | 2011-03-02 16:54:24 +0900 | [diff] [blame] | 930 | 	int error = 0; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 931 | 	struct tomoyo_path_info buf; | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 932 | 	struct tomoyo_request_info r; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 933 | 	int idx; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 934 |  | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 935 | 	if (!path->mnt || | 
 | 936 | 	    (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 937 | 		return 0; | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 938 | 	buf.name = NULL; | 
 | 939 | 	r.mode = TOMOYO_CONFIG_DISABLED; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 940 | 	idx = tomoyo_read_lock(); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 941 | 	/* | 
 | 942 | 	 * If the filename is specified by "deny_rewrite" keyword, | 
 | 943 | 	 * we need to check "allow_rewrite" permission when the filename is not | 
 | 944 | 	 * opened for append mode or the filename is truncated at open time. | 
 | 945 | 	 */ | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 946 | 	if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) | 
 | 947 | 	    && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) | 
 | 948 | 	    != TOMOYO_CONFIG_DISABLED) { | 
 | 949 | 		if (!tomoyo_get_realpath(&buf, path)) { | 
 | 950 | 			error = -ENOMEM; | 
 | 951 | 			goto out; | 
 | 952 | 		} | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 953 | 		if (tomoyo_no_rewrite_file(&buf)) | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 954 | 			error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, | 
 | 955 | 						       &buf); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 956 | 	} | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 957 | 	if (!error && acc_mode && | 
 | 958 | 	    tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) | 
 | 959 | 	    != TOMOYO_CONFIG_DISABLED) { | 
| Tetsuo Handa | 05336de | 2010-06-16 16:20:24 +0900 | [diff] [blame] | 960 | 		u8 operation; | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 961 | 		if (!buf.name && !tomoyo_get_realpath(&buf, path)) { | 
 | 962 | 			error = -ENOMEM; | 
 | 963 | 			goto out; | 
 | 964 | 		} | 
| Tetsuo Handa | 05336de | 2010-06-16 16:20:24 +0900 | [diff] [blame] | 965 | 		if (acc_mode == (MAY_READ | MAY_WRITE)) | 
 | 966 | 			operation = TOMOYO_TYPE_READ_WRITE; | 
 | 967 | 		else if (acc_mode == MAY_READ) | 
 | 968 | 			operation = TOMOYO_TYPE_READ; | 
 | 969 | 		else | 
 | 970 | 			operation = TOMOYO_TYPE_WRITE; | 
 | 971 | 		error = tomoyo_path_permission(&r, operation, &buf); | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 972 | 	} | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 973 |  out: | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 974 | 	kfree(buf.name); | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 975 | 	tomoyo_read_unlock(idx); | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 976 | 	if (r.mode != TOMOYO_CONFIG_ENFORCING) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 977 | 		error = 0; | 
 | 978 | 	return error; | 
 | 979 | } | 
 | 980 |  | 
 | 981 | /** | 
| Tetsuo Handa | 2106ccd | 2010-05-17 10:10:31 +0900 | [diff] [blame] | 982 |  * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount". | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 983 |  * | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 984 |  * @operation: Type of operation. | 
 | 985 |  * @path:      Pointer to "struct path". | 
 | 986 |  * | 
 | 987 |  * Returns 0 on success, negative value otherwise. | 
 | 988 |  */ | 
| Tetsuo Handa | 97d6931 | 2010-02-16 09:46:15 +0900 | [diff] [blame] | 989 | int tomoyo_path_perm(const u8 operation, struct path *path) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 990 | { | 
 | 991 | 	int error = -ENOMEM; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 992 | 	struct tomoyo_path_info buf; | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 993 | 	struct tomoyo_request_info r; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 994 | 	int idx; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 995 |  | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 996 | 	if (!path->mnt) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 997 | 		return 0; | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 998 | 	if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) | 
 | 999 | 	    == TOMOYO_CONFIG_DISABLED) | 
 | 1000 | 		return 0; | 
 | 1001 | 	buf.name = NULL; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 1002 | 	idx = tomoyo_read_lock(); | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1003 | 	if (!tomoyo_get_realpath(&buf, path)) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1004 | 		goto out; | 
 | 1005 | 	switch (operation) { | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 1006 | 	case TOMOYO_TYPE_REWRITE: | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 1007 | 		if (!tomoyo_no_rewrite_file(&buf)) { | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 1008 | 			error = 0; | 
 | 1009 | 			goto out; | 
 | 1010 | 		} | 
 | 1011 | 		break; | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 1012 | 	case TOMOYO_TYPE_RMDIR: | 
 | 1013 | 	case TOMOYO_TYPE_CHROOT: | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1014 | 		tomoyo_add_slash(&buf); | 
 | 1015 | 		break; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1016 | 	} | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1017 | 	error = tomoyo_path_permission(&r, operation, &buf); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1018 |  out: | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1019 | 	kfree(buf.name); | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 1020 | 	tomoyo_read_unlock(idx); | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 1021 | 	if (r.mode != TOMOYO_CONFIG_ENFORCING) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1022 | 		error = 0; | 
 | 1023 | 	return error; | 
 | 1024 | } | 
 | 1025 |  | 
 | 1026 | /** | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 1027 |  * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1028 |  * | 
 | 1029 |  * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) | 
 | 1030 |  * @path:      Pointer to "struct path". | 
 | 1031 |  * @mode:      Create mode. | 
 | 1032 |  * @dev:       Device number. | 
 | 1033 |  * | 
 | 1034 |  * Returns 0 on success, negative value otherwise. | 
 | 1035 |  */ | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 1036 | int tomoyo_mkdev_perm(const u8 operation, struct path *path, | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1037 | 			     const unsigned int mode, unsigned int dev) | 
 | 1038 | { | 
 | 1039 | 	struct tomoyo_request_info r; | 
 | 1040 | 	int error = -ENOMEM; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1041 | 	struct tomoyo_path_info buf; | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1042 | 	int idx; | 
 | 1043 |  | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 1044 | 	if (!path->mnt || | 
 | 1045 | 	    tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) | 
 | 1046 | 	    == TOMOYO_CONFIG_DISABLED) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1047 | 		return 0; | 
 | 1048 | 	idx = tomoyo_read_lock(); | 
 | 1049 | 	error = -ENOMEM; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1050 | 	if (tomoyo_get_realpath(&buf, path)) { | 
| Tetsuo Handa | cf6e9a6 | 2010-06-16 16:21:36 +0900 | [diff] [blame] | 1051 | 		dev = new_decode_dev(dev); | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 1052 | 		r.param_type = TOMOYO_TYPE_MKDEV_ACL; | 
| Tetsuo Handa | cf6e9a6 | 2010-06-16 16:21:36 +0900 | [diff] [blame] | 1053 | 		r.param.mkdev.filename = &buf; | 
 | 1054 | 		r.param.mkdev.operation = operation; | 
 | 1055 | 		r.param.mkdev.mode = mode; | 
 | 1056 | 		r.param.mkdev.major = MAJOR(dev); | 
 | 1057 | 		r.param.mkdev.minor = MINOR(dev); | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 1058 | 		tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); | 
 | 1059 | 		error = tomoyo_audit_mkdev_log(&r); | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1060 | 		kfree(buf.name); | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1061 | 	} | 
 | 1062 | 	tomoyo_read_unlock(idx); | 
 | 1063 | 	if (r.mode != TOMOYO_CONFIG_ENFORCING) | 
 | 1064 | 		error = 0; | 
 | 1065 | 	return error; | 
 | 1066 | } | 
 | 1067 |  | 
 | 1068 | /** | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 1069 |  * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1070 |  * | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1071 |  * @operation: Type of operation. | 
 | 1072 |  * @path1:      Pointer to "struct path". | 
 | 1073 |  * @path2:      Pointer to "struct path". | 
 | 1074 |  * | 
 | 1075 |  * Returns 0 on success, negative value otherwise. | 
 | 1076 |  */ | 
| Tetsuo Handa | 97d6931 | 2010-02-16 09:46:15 +0900 | [diff] [blame] | 1077 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | 
| Tetsuo Handa | 7ef6123 | 2010-02-16 08:03:30 +0900 | [diff] [blame] | 1078 | 		      struct path *path2) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1079 | { | 
 | 1080 | 	int error = -ENOMEM; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1081 | 	struct tomoyo_path_info buf1; | 
 | 1082 | 	struct tomoyo_path_info buf2; | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 1083 | 	struct tomoyo_request_info r; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 1084 | 	int idx; | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1085 |  | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 1086 | 	if (!path1->mnt || !path2->mnt || | 
 | 1087 | 	    tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) | 
 | 1088 | 	    == TOMOYO_CONFIG_DISABLED) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1089 | 		return 0; | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1090 | 	buf1.name = NULL; | 
 | 1091 | 	buf2.name = NULL; | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 1092 | 	idx = tomoyo_read_lock(); | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1093 | 	if (!tomoyo_get_realpath(&buf1, path1) || | 
 | 1094 | 	    !tomoyo_get_realpath(&buf2, path2)) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1095 | 		goto out; | 
| Tetsuo Handa | 57c2590 | 2010-06-03 20:38:44 +0900 | [diff] [blame] | 1096 | 	switch (operation) { | 
 | 1097 | 		struct dentry *dentry; | 
 | 1098 | 	case TOMOYO_TYPE_RENAME: | 
 | 1099 |         case TOMOYO_TYPE_LINK: | 
 | 1100 | 		dentry = path1->dentry; | 
 | 1101 | 	        if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) | 
 | 1102 |                         break; | 
 | 1103 |                 /* fall through */ | 
 | 1104 |         case TOMOYO_TYPE_PIVOT_ROOT: | 
 | 1105 |                 tomoyo_add_slash(&buf1); | 
 | 1106 |                 tomoyo_add_slash(&buf2); | 
 | 1107 | 		break; | 
 | 1108 |         } | 
| Tetsuo Handa | cf6e9a6 | 2010-06-16 16:21:36 +0900 | [diff] [blame] | 1109 | 	r.param_type = TOMOYO_TYPE_PATH2_ACL; | 
 | 1110 | 	r.param.path2.operation = operation; | 
 | 1111 | 	r.param.path2.filename1 = &buf1; | 
 | 1112 | 	r.param.path2.filename2 = &buf2; | 
| Tetsuo Handa | 17fcfbd | 2010-05-17 10:11:36 +0900 | [diff] [blame] | 1113 | 	do { | 
| Tetsuo Handa | 99a8525 | 2010-06-16 16:22:51 +0900 | [diff] [blame] | 1114 | 		tomoyo_check_acl(&r, tomoyo_check_path2_acl); | 
 | 1115 | 		error = tomoyo_audit_path2_log(&r); | 
 | 1116 | 	} while (error == TOMOYO_RETRY_REQUEST); | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1117 |  out: | 
| Tetsuo Handa | c8c57e8 | 2010-06-03 20:36:43 +0900 | [diff] [blame] | 1118 | 	kfree(buf1.name); | 
 | 1119 | 	kfree(buf2.name); | 
| Tetsuo Handa | fdb8ebb | 2009-12-08 09:34:43 +0900 | [diff] [blame] | 1120 | 	tomoyo_read_unlock(idx); | 
| Tetsuo Handa | cb0abe6 | 2010-05-17 10:08:05 +0900 | [diff] [blame] | 1121 | 	if (r.mode != TOMOYO_CONFIG_ENFORCING) | 
| Kentaro Takeda | b69a54e | 2009-02-05 17:18:14 +0900 | [diff] [blame] | 1122 | 		error = 0; | 
 | 1123 | 	return error; | 
 | 1124 | } | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1125 |  | 
 | 1126 | /** | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 1127 |  * tomoyo_write_file - Update file related list. | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1128 |  * | 
 | 1129 |  * @data:      String to parse. | 
 | 1130 |  * @domain:    Pointer to "struct tomoyo_domain_info". | 
 | 1131 |  * @is_delete: True if it is a delete request. | 
 | 1132 |  * | 
 | 1133 |  * Returns 0 on success, negative value otherwise. | 
 | 1134 |  * | 
 | 1135 |  * Caller holds tomoyo_read_lock(). | 
 | 1136 |  */ | 
| Tetsuo Handa | e2bf690 | 2010-06-25 11:16:00 +0900 | [diff] [blame] | 1137 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, | 
 | 1138 | 		      const bool is_delete) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1139 | { | 
 | 1140 | 	char *w[5]; | 
 | 1141 | 	u8 type; | 
 | 1142 | 	if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) | 
 | 1143 | 		return -EINVAL; | 
| Tetsuo Handa | 237ab45 | 2010-06-12 20:46:22 +0900 | [diff] [blame] | 1144 | 	if (strncmp(w[0], "allow_", 6)) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1145 | 		goto out; | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1146 | 	w[0] += 6; | 
 | 1147 | 	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { | 
 | 1148 | 		if (strcmp(w[0], tomoyo_path_keyword[type])) | 
 | 1149 | 			continue; | 
 | 1150 | 		return tomoyo_update_path_acl(type, w[1], domain, is_delete); | 
 | 1151 | 	} | 
 | 1152 | 	if (!w[2][0]) | 
 | 1153 | 		goto out; | 
 | 1154 | 	for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { | 
 | 1155 | 		if (strcmp(w[0], tomoyo_path2_keyword[type])) | 
 | 1156 | 			continue; | 
 | 1157 | 		return tomoyo_update_path2_acl(type, w[1], w[2], domain, | 
 | 1158 | 					       is_delete); | 
 | 1159 | 	} | 
 | 1160 | 	for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { | 
 | 1161 | 		if (strcmp(w[0], tomoyo_path_number_keyword[type])) | 
 | 1162 | 			continue; | 
 | 1163 | 		return tomoyo_update_path_number_acl(type, w[1], w[2], domain, | 
 | 1164 | 						     is_delete); | 
 | 1165 | 	} | 
 | 1166 | 	if (!w[3][0] || !w[4][0]) | 
 | 1167 | 		goto out; | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 1168 | 	for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) { | 
 | 1169 | 		if (strcmp(w[0], tomoyo_mkdev_keyword[type])) | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1170 | 			continue; | 
| Tetsuo Handa | 7509315 | 2010-06-16 16:23:55 +0900 | [diff] [blame] | 1171 | 		return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3], | 
 | 1172 | 					       w[4], domain, is_delete); | 
| Tetsuo Handa | a1f9bb6 | 2010-05-17 10:09:15 +0900 | [diff] [blame] | 1173 | 	} | 
 | 1174 |  out: | 
 | 1175 | 	return -EINVAL; | 
 | 1176 | } |