Linux Audio

Check our new training course

Loading...
v4.6
   1/*
   2 * security/tomoyo/file.c
   3 *
   4 * Copyright (C) 2005-2011  NTT DATA CORPORATION
   5 */
   6
   7#include "common.h"
   8#include <linux/slab.h>
   9
  10/*
  11 * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
  12 */
  13static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
  14	[TOMOYO_TYPE_EXECUTE]    = TOMOYO_MAC_FILE_EXECUTE,
  15	[TOMOYO_TYPE_READ]       = TOMOYO_MAC_FILE_OPEN,
  16	[TOMOYO_TYPE_WRITE]      = TOMOYO_MAC_FILE_OPEN,
  17	[TOMOYO_TYPE_APPEND]     = TOMOYO_MAC_FILE_OPEN,
  18	[TOMOYO_TYPE_UNLINK]     = TOMOYO_MAC_FILE_UNLINK,
  19	[TOMOYO_TYPE_GETATTR]    = TOMOYO_MAC_FILE_GETATTR,
  20	[TOMOYO_TYPE_RMDIR]      = TOMOYO_MAC_FILE_RMDIR,
  21	[TOMOYO_TYPE_TRUNCATE]   = TOMOYO_MAC_FILE_TRUNCATE,
  22	[TOMOYO_TYPE_SYMLINK]    = TOMOYO_MAC_FILE_SYMLINK,
  23	[TOMOYO_TYPE_CHROOT]     = TOMOYO_MAC_FILE_CHROOT,
  24	[TOMOYO_TYPE_UMOUNT]     = TOMOYO_MAC_FILE_UMOUNT,
  25};
  26
  27/*
  28 * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
  29 */
  30const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
  31	[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
  32	[TOMOYO_TYPE_MKCHAR]  = TOMOYO_MAC_FILE_MKCHAR,
  33};
  34
  35/*
  36 * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
  37 */
  38const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
  39	[TOMOYO_TYPE_LINK]       = TOMOYO_MAC_FILE_LINK,
  40	[TOMOYO_TYPE_RENAME]     = TOMOYO_MAC_FILE_RENAME,
  41	[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
  42};
  43
  44/*
  45 * Mapping table from "enum tomoyo_path_number_acl_index" to
  46 * "enum tomoyo_mac_index".
  47 */
  48const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
  49	[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
  50	[TOMOYO_TYPE_MKDIR]  = TOMOYO_MAC_FILE_MKDIR,
  51	[TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
  52	[TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
  53	[TOMOYO_TYPE_IOCTL]  = TOMOYO_MAC_FILE_IOCTL,
  54	[TOMOYO_TYPE_CHMOD]  = TOMOYO_MAC_FILE_CHMOD,
  55	[TOMOYO_TYPE_CHOWN]  = TOMOYO_MAC_FILE_CHOWN,
  56	[TOMOYO_TYPE_CHGRP]  = TOMOYO_MAC_FILE_CHGRP,
  57};
  58
  59/**
  60 * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
  61 *
  62 * @ptr: Pointer to "struct tomoyo_name_union".
  63 *
  64 * Returns nothing.
  65 */
  66void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
  67{
  68	tomoyo_put_group(ptr->group);
  69	tomoyo_put_name(ptr->filename);
  70}
  71
  72/**
  73 * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
  74 *
  75 * @name: Pointer to "struct tomoyo_path_info".
  76 * @ptr:  Pointer to "struct tomoyo_name_union".
  77 *
  78 * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
  79 */
  80const struct tomoyo_path_info *
  81tomoyo_compare_name_union(const struct tomoyo_path_info *name,
  82			  const struct tomoyo_name_union *ptr)
  83{
  84	if (ptr->group)
  85		return tomoyo_path_matches_group(name, ptr->group);
  86	if (tomoyo_path_matches_pattern(name, ptr->filename))
  87		return ptr->filename;
  88	return NULL;
  89}
  90
  91/**
  92 * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
  93 *
  94 * @ptr: Pointer to "struct tomoyo_number_union".
  95 *
  96 * Returns nothing.
  97 */
  98void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
  99{
 100	tomoyo_put_group(ptr->group);
 101}
 102
 103/**
 104 * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
 105 *
 106 * @value: Number to check.
 107 * @ptr:   Pointer to "struct tomoyo_number_union".
 108 *
 109 * Returns true if @value matches @ptr, false otherwise.
 110 */
 111bool tomoyo_compare_number_union(const unsigned long value,
 112				 const struct tomoyo_number_union *ptr)
 113{
 114	if (ptr->group)
 115		return tomoyo_number_matches_group(value, value, ptr->group);
 116	return value >= ptr->values[0] && value <= ptr->values[1];
 117}
 118
 119/**
 120 * tomoyo_add_slash - Add trailing '/' if needed.
 121 *
 122 * @buf: Pointer to "struct tomoyo_path_info".
 123 *
 124 * Returns nothing.
 125 *
 126 * @buf must be generated by tomoyo_encode() because this function does not
 127 * allocate memory for adding '/'.
 128 */
 129static void tomoyo_add_slash(struct tomoyo_path_info *buf)
 130{
 131	if (buf->is_dir)
 132		return;
 133	/*
 134	 * This is OK because tomoyo_encode() reserves space for appending "/".
 135	 */
 136	strcat((char *) buf->name, "/");
 137	tomoyo_fill_path_info(buf);
 138}
 139
 140/**
 141 * tomoyo_get_realpath - Get realpath.
 142 *
 143 * @buf:  Pointer to "struct tomoyo_path_info".
 144 * @path: Pointer to "struct path".
 145 *
 146 * Returns true on success, false otherwise.
 147 */
 148static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
 149{
 150	buf->name = tomoyo_realpath_from_path(path);
 151	if (buf->name) {
 152		tomoyo_fill_path_info(buf);
 153		return true;
 154	}
 155	return false;
 156}
 157
 158/**
 159 * tomoyo_audit_path_log - Audit path request log.
 160 *
 161 * @r: Pointer to "struct tomoyo_request_info".
 162 *
 163 * Returns 0 on success, negative value otherwise.
 164 */
 165static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
 166{
 167	return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
 168				 [r->param.path.operation],
 169				 r->param.path.filename->name);
 170}
 171
 172/**
 173 * tomoyo_audit_path2_log - Audit path/path request log.
 174 *
 175 * @r: Pointer to "struct tomoyo_request_info".
 176 *
 177 * Returns 0 on success, negative value otherwise.
 178 */
 179static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
 180{
 181	return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
 182				 [tomoyo_pp2mac[r->param.path2.operation]],
 183				 r->param.path2.filename1->name,
 184				 r->param.path2.filename2->name);
 185}
 186
 187/**
 188 * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
 189 *
 190 * @r: Pointer to "struct tomoyo_request_info".
 191 *
 192 * Returns 0 on success, negative value otherwise.
 193 */
 194static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
 195{
 196	return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
 197				 tomoyo_mac_keywords
 198				 [tomoyo_pnnn2mac[r->param.mkdev.operation]],
 199				 r->param.mkdev.filename->name,
 200				 r->param.mkdev.mode, r->param.mkdev.major,
 201				 r->param.mkdev.minor);
 202}
 203
 204/**
 205 * tomoyo_audit_path_number_log - Audit path/number request log.
 206 *
 207 * @r: Pointer to "struct tomoyo_request_info".
 208 *
 209 * Returns 0 on success, negative value otherwise.
 210 */
 211static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
 212{
 213	const u8 type = r->param.path_number.operation;
 214	u8 radix;
 215	char buffer[64];
 216	switch (type) {
 217	case TOMOYO_TYPE_CREATE:
 218	case TOMOYO_TYPE_MKDIR:
 219	case TOMOYO_TYPE_MKFIFO:
 220	case TOMOYO_TYPE_MKSOCK:
 221	case TOMOYO_TYPE_CHMOD:
 222		radix = TOMOYO_VALUE_TYPE_OCTAL;
 223		break;
 224	case TOMOYO_TYPE_IOCTL:
 225		radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
 226		break;
 227	default:
 228		radix = TOMOYO_VALUE_TYPE_DECIMAL;
 229		break;
 230	}
 231	tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
 232			   radix);
 233	return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
 234				 [tomoyo_pn2mac[type]],
 235				 r->param.path_number.filename->name, buffer);
 236}
 237
 238/**
 239 * tomoyo_check_path_acl - Check permission for path operation.
 240 *
 241 * @r:   Pointer to "struct tomoyo_request_info".
 242 * @ptr: Pointer to "struct tomoyo_acl_info".
 243 *
 244 * Returns true if granted, false otherwise.
 245 *
 246 * To be able to use wildcard for domain transition, this function sets
 247 * matching entry on success. Since the caller holds tomoyo_read_lock(),
 248 * it is safe to set matching entry.
 249 */
 250static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
 251				  const struct tomoyo_acl_info *ptr)
 252{
 253	const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
 254							 head);
 255	if (acl->perm & (1 << r->param.path.operation)) {
 256		r->param.path.matched_path =
 257			tomoyo_compare_name_union(r->param.path.filename,
 258						  &acl->name);
 259		return r->param.path.matched_path != NULL;
 260	}
 261	return false;
 262}
 263
 264/**
 265 * tomoyo_check_path_number_acl - Check permission for path number operation.
 266 *
 267 * @r:   Pointer to "struct tomoyo_request_info".
 268 * @ptr: Pointer to "struct tomoyo_acl_info".
 269 *
 270 * Returns true if granted, false otherwise.
 271 */
 272static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
 273					 const struct tomoyo_acl_info *ptr)
 274{
 275	const struct tomoyo_path_number_acl *acl =
 276		container_of(ptr, typeof(*acl), head);
 277	return (acl->perm & (1 << r->param.path_number.operation)) &&
 278		tomoyo_compare_number_union(r->param.path_number.number,
 279					    &acl->number) &&
 280		tomoyo_compare_name_union(r->param.path_number.filename,
 281					  &acl->name);
 282}
 283
 284/**
 285 * tomoyo_check_path2_acl - Check permission for path path operation.
 286 *
 287 * @r:   Pointer to "struct tomoyo_request_info".
 288 * @ptr: Pointer to "struct tomoyo_acl_info".
 289 *
 290 * Returns true if granted, false otherwise.
 291 */
 292static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
 293				   const struct tomoyo_acl_info *ptr)
 294{
 295	const struct tomoyo_path2_acl *acl =
 296		container_of(ptr, typeof(*acl), head);
 297	return (acl->perm & (1 << r->param.path2.operation)) &&
 298		tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
 299		&& tomoyo_compare_name_union(r->param.path2.filename2,
 300					     &acl->name2);
 301}
 302
 303/**
 304 * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
 305 *
 306 * @r:   Pointer to "struct tomoyo_request_info".
 307 * @ptr: Pointer to "struct tomoyo_acl_info".
 308 *
 309 * Returns true if granted, false otherwise.
 310 */
 311static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
 312				   const struct tomoyo_acl_info *ptr)
 313{
 314	const struct tomoyo_mkdev_acl *acl =
 315		container_of(ptr, typeof(*acl), head);
 316	return (acl->perm & (1 << r->param.mkdev.operation)) &&
 317		tomoyo_compare_number_union(r->param.mkdev.mode,
 318					    &acl->mode) &&
 319		tomoyo_compare_number_union(r->param.mkdev.major,
 320					    &acl->major) &&
 321		tomoyo_compare_number_union(r->param.mkdev.minor,
 322					    &acl->minor) &&
 323		tomoyo_compare_name_union(r->param.mkdev.filename,
 324					  &acl->name);
 325}
 326
 327/**
 328 * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
 329 *
 330 * @a: Pointer to "struct tomoyo_acl_info".
 331 * @b: Pointer to "struct tomoyo_acl_info".
 332 *
 333 * Returns true if @a == @b except permission bits, false otherwise.
 334 */
 335static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
 336				 const struct tomoyo_acl_info *b)
 337{
 338	const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
 339	const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
 340	return tomoyo_same_name_union(&p1->name, &p2->name);
 341}
 342
 343/**
 344 * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
 345 *
 346 * @a:         Pointer to "struct tomoyo_acl_info".
 347 * @b:         Pointer to "struct tomoyo_acl_info".
 348 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 349 *
 350 * Returns true if @a is empty, false otherwise.
 351 */
 352static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
 353				  struct tomoyo_acl_info *b,
 354				  const bool is_delete)
 355{
 356	u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
 357		->perm;
 358	u16 perm = *a_perm;
 359	const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
 360	if (is_delete)
 361		perm &= ~b_perm;
 362	else
 363		perm |= b_perm;
 364	*a_perm = perm;
 365	return !perm;
 366}
 367
 368/**
 369 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
 370 *
 371 * @perm:  Permission.
 372 * @param: Pointer to "struct tomoyo_acl_param".
 373 *
 374 * Returns 0 on success, negative value otherwise.
 375 *
 376 * Caller holds tomoyo_read_lock().
 377 */
 378static int tomoyo_update_path_acl(const u16 perm,
 379				  struct tomoyo_acl_param *param)
 380{
 381	struct tomoyo_path_acl e = {
 382		.head.type = TOMOYO_TYPE_PATH_ACL,
 383		.perm = perm
 384	};
 385	int error;
 386	if (!tomoyo_parse_name_union(param, &e.name))
 387		error = -EINVAL;
 388	else
 389		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 390					     tomoyo_same_path_acl,
 391					     tomoyo_merge_path_acl);
 392	tomoyo_put_name_union(&e.name);
 393	return error;
 394}
 395
 396/**
 397 * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
 398 *
 399 * @a: Pointer to "struct tomoyo_acl_info".
 400 * @b: Pointer to "struct tomoyo_acl_info".
 401 *
 402 * Returns true if @a == @b except permission bits, false otherwise.
 403 */
 404static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
 405					 const struct tomoyo_acl_info *b)
 406{
 407	const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
 408	const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
 409	return tomoyo_same_name_union(&p1->name, &p2->name) &&
 410		tomoyo_same_number_union(&p1->mode, &p2->mode) &&
 411		tomoyo_same_number_union(&p1->major, &p2->major) &&
 412		tomoyo_same_number_union(&p1->minor, &p2->minor);
 413}
 414
 415/**
 416 * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
 417 *
 418 * @a:         Pointer to "struct tomoyo_acl_info".
 419 * @b:         Pointer to "struct tomoyo_acl_info".
 420 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 421 *
 422 * Returns true if @a is empty, false otherwise.
 423 */
 424static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
 425				   struct tomoyo_acl_info *b,
 426				   const bool is_delete)
 427{
 428	u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
 429					 head)->perm;
 430	u8 perm = *a_perm;
 431	const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
 432		->perm;
 433	if (is_delete)
 434		perm &= ~b_perm;
 435	else
 436		perm |= b_perm;
 437	*a_perm = perm;
 438	return !perm;
 439}
 440
 441/**
 442 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
 443 *
 444 * @perm:  Permission.
 445 * @param: Pointer to "struct tomoyo_acl_param".
 446 *
 447 * Returns 0 on success, negative value otherwise.
 448 *
 449 * Caller holds tomoyo_read_lock().
 450 */
 451static int tomoyo_update_mkdev_acl(const u8 perm,
 452				   struct tomoyo_acl_param *param)
 453{
 454	struct tomoyo_mkdev_acl e = {
 455		.head.type = TOMOYO_TYPE_MKDEV_ACL,
 456		.perm = perm
 457	};
 458	int error;
 459	if (!tomoyo_parse_name_union(param, &e.name) ||
 460	    !tomoyo_parse_number_union(param, &e.mode) ||
 461	    !tomoyo_parse_number_union(param, &e.major) ||
 462	    !tomoyo_parse_number_union(param, &e.minor))
 463		error = -EINVAL;
 464	else
 465		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 466					     tomoyo_same_mkdev_acl,
 467					     tomoyo_merge_mkdev_acl);
 468	tomoyo_put_name_union(&e.name);
 469	tomoyo_put_number_union(&e.mode);
 470	tomoyo_put_number_union(&e.major);
 471	tomoyo_put_number_union(&e.minor);
 472	return error;
 473}
 474
 475/**
 476 * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
 477 *
 478 * @a: Pointer to "struct tomoyo_acl_info".
 479 * @b: Pointer to "struct tomoyo_acl_info".
 480 *
 481 * Returns true if @a == @b except permission bits, false otherwise.
 482 */
 483static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
 484				  const struct tomoyo_acl_info *b)
 485{
 486	const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
 487	const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
 488	return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
 489		tomoyo_same_name_union(&p1->name2, &p2->name2);
 490}
 491
 492/**
 493 * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
 494 *
 495 * @a:         Pointer to "struct tomoyo_acl_info".
 496 * @b:         Pointer to "struct tomoyo_acl_info".
 497 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 498 *
 499 * Returns true if @a is empty, false otherwise.
 500 */
 501static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
 502				   struct tomoyo_acl_info *b,
 503				   const bool is_delete)
 504{
 505	u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
 506		->perm;
 507	u8 perm = *a_perm;
 508	const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
 509	if (is_delete)
 510		perm &= ~b_perm;
 511	else
 512		perm |= b_perm;
 513	*a_perm = perm;
 514	return !perm;
 515}
 516
 517/**
 518 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
 519 *
 520 * @perm:  Permission.
 521 * @param: Pointer to "struct tomoyo_acl_param".
 522 *
 523 * Returns 0 on success, negative value otherwise.
 524 *
 525 * Caller holds tomoyo_read_lock().
 526 */
 527static int tomoyo_update_path2_acl(const u8 perm,
 528				   struct tomoyo_acl_param *param)
 529{
 530	struct tomoyo_path2_acl e = {
 531		.head.type = TOMOYO_TYPE_PATH2_ACL,
 532		.perm = perm
 533	};
 534	int error;
 535	if (!tomoyo_parse_name_union(param, &e.name1) ||
 536	    !tomoyo_parse_name_union(param, &e.name2))
 537		error = -EINVAL;
 538	else
 539		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 540					     tomoyo_same_path2_acl,
 541					     tomoyo_merge_path2_acl);
 542	tomoyo_put_name_union(&e.name1);
 543	tomoyo_put_name_union(&e.name2);
 544	return error;
 545}
 546
 547/**
 548 * tomoyo_path_permission - Check permission for single path operation.
 549 *
 550 * @r:         Pointer to "struct tomoyo_request_info".
 551 * @operation: Type of operation.
 552 * @filename:  Filename to check.
 553 *
 554 * Returns 0 on success, negative value otherwise.
 555 *
 556 * Caller holds tomoyo_read_lock().
 557 */
 558static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
 559				  const struct tomoyo_path_info *filename)
 560{
 561	int error;
 562
 563	r->type = tomoyo_p2mac[operation];
 564	r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
 565	if (r->mode == TOMOYO_CONFIG_DISABLED)
 566		return 0;
 567	r->param_type = TOMOYO_TYPE_PATH_ACL;
 568	r->param.path.filename = filename;
 569	r->param.path.operation = operation;
 570	do {
 571		tomoyo_check_acl(r, tomoyo_check_path_acl);
 572		error = tomoyo_audit_path_log(r);
 573	} while (error == TOMOYO_RETRY_REQUEST);
 574	return error;
 575}
 576
 577/**
 578 * tomoyo_execute_permission - Check permission for execute operation.
 579 *
 580 * @r:         Pointer to "struct tomoyo_request_info".
 581 * @filename:  Filename to check.
 582 *
 583 * Returns 0 on success, negative value otherwise.
 584 *
 585 * Caller holds tomoyo_read_lock().
 586 */
 587int tomoyo_execute_permission(struct tomoyo_request_info *r,
 588			      const struct tomoyo_path_info *filename)
 589{
 590	/*
 591	 * Unlike other permission checks, this check is done regardless of
 592	 * profile mode settings in order to check for domain transition
 593	 * preference.
 594	 */
 595	r->type = TOMOYO_MAC_FILE_EXECUTE;
 596	r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
 597	r->param_type = TOMOYO_TYPE_PATH_ACL;
 598	r->param.path.filename = filename;
 599	r->param.path.operation = TOMOYO_TYPE_EXECUTE;
 600	tomoyo_check_acl(r, tomoyo_check_path_acl);
 601	r->ee->transition = r->matched_acl && r->matched_acl->cond ?
 602		r->matched_acl->cond->transit : NULL;
 603	if (r->mode != TOMOYO_CONFIG_DISABLED)
 604		return tomoyo_audit_path_log(r);
 605	return 0;
 606}
 607
 608/**
 609 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
 610 *
 611 * @a: Pointer to "struct tomoyo_acl_info".
 612 * @b: Pointer to "struct tomoyo_acl_info".
 613 *
 614 * Returns true if @a == @b except permission bits, false otherwise.
 615 */
 616static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
 617					const struct tomoyo_acl_info *b)
 618{
 619	const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
 620							       head);
 621	const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
 622							       head);
 623	return tomoyo_same_name_union(&p1->name, &p2->name) &&
 624		tomoyo_same_number_union(&p1->number, &p2->number);
 625}
 626
 627/**
 628 * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
 629 *
 630 * @a:         Pointer to "struct tomoyo_acl_info".
 631 * @b:         Pointer to "struct tomoyo_acl_info".
 632 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 633 *
 634 * Returns true if @a is empty, false otherwise.
 635 */
 636static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
 637					 struct tomoyo_acl_info *b,
 638					 const bool is_delete)
 639{
 640	u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
 641					  head)->perm;
 642	u8 perm = *a_perm;
 643	const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
 644		->perm;
 645	if (is_delete)
 646		perm &= ~b_perm;
 647	else
 648		perm |= b_perm;
 649	*a_perm = perm;
 650	return !perm;
 651}
 652
 653/**
 654 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
 655 *
 656 * @perm:  Permission.
 657 * @param: Pointer to "struct tomoyo_acl_param".
 658 *
 659 * Returns 0 on success, negative value otherwise.
 660 */
 661static int tomoyo_update_path_number_acl(const u8 perm,
 662					 struct tomoyo_acl_param *param)
 663{
 664	struct tomoyo_path_number_acl e = {
 665		.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
 666		.perm = perm
 667	};
 668	int error;
 669	if (!tomoyo_parse_name_union(param, &e.name) ||
 670	    !tomoyo_parse_number_union(param, &e.number))
 671		error = -EINVAL;
 672	else
 673		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 674					     tomoyo_same_path_number_acl,
 675					     tomoyo_merge_path_number_acl);
 676	tomoyo_put_name_union(&e.name);
 677	tomoyo_put_number_union(&e.number);
 678	return error;
 679}
 680
 681/**
 682 * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
 683 *
 684 * @type:   Type of operation.
 685 * @path:   Pointer to "struct path".
 686 * @number: Number.
 687 *
 688 * Returns 0 on success, negative value otherwise.
 689 */
 690int tomoyo_path_number_perm(const u8 type, struct path *path,
 691			    unsigned long number)
 692{
 693	struct tomoyo_request_info r;
 694	struct tomoyo_obj_info obj = {
 695		.path1 = *path,
 696	};
 697	int error = -ENOMEM;
 698	struct tomoyo_path_info buf;
 699	int idx;
 700
 701	if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
 702	    == TOMOYO_CONFIG_DISABLED || !path->dentry)
 703		return 0;
 704	idx = tomoyo_read_lock();
 705	if (!tomoyo_get_realpath(&buf, path))
 706		goto out;
 707	r.obj = &obj;
 708	if (type == TOMOYO_TYPE_MKDIR)
 709		tomoyo_add_slash(&buf);
 710	r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
 711	r.param.path_number.operation = type;
 712	r.param.path_number.filename = &buf;
 713	r.param.path_number.number = number;
 714	do {
 715		tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
 716		error = tomoyo_audit_path_number_log(&r);
 717	} while (error == TOMOYO_RETRY_REQUEST);
 718	kfree(buf.name);
 719 out:
 720	tomoyo_read_unlock(idx);
 721	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 722		error = 0;
 723	return error;
 724}
 725
 726/**
 727 * tomoyo_check_open_permission - Check permission for "read" and "write".
 728 *
 729 * @domain: Pointer to "struct tomoyo_domain_info".
 730 * @path:   Pointer to "struct path".
 731 * @flag:   Flags for open().
 732 *
 733 * Returns 0 on success, negative value otherwise.
 734 */
 735int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 736				 struct path *path, const int flag)
 737{
 738	const u8 acc_mode = ACC_MODE(flag);
 739	int error = 0;
 740	struct tomoyo_path_info buf;
 741	struct tomoyo_request_info r;
 742	struct tomoyo_obj_info obj = {
 743		.path1 = *path,
 744	};
 745	int idx;
 746
 747	buf.name = NULL;
 748	r.mode = TOMOYO_CONFIG_DISABLED;
 749	idx = tomoyo_read_lock();
 750	if (acc_mode &&
 751	    tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
 752	    != TOMOYO_CONFIG_DISABLED) {
 753		if (!tomoyo_get_realpath(&buf, path)) {
 754			error = -ENOMEM;
 755			goto out;
 756		}
 757		r.obj = &obj;
 758		if (acc_mode & MAY_READ)
 759			error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
 760						       &buf);
 761		if (!error && (acc_mode & MAY_WRITE))
 762			error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
 763						       TOMOYO_TYPE_APPEND :
 764						       TOMOYO_TYPE_WRITE,
 765						       &buf);
 766	}
 767 out:
 768	kfree(buf.name);
 769	tomoyo_read_unlock(idx);
 770	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 771		error = 0;
 772	return error;
 773}
 774
 775/**
 776 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
 777 *
 778 * @operation: Type of operation.
 779 * @path:      Pointer to "struct path".
 780 * @target:    Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
 781 *             NULL otherwise.
 782 *
 783 * Returns 0 on success, negative value otherwise.
 784 */
 785int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
 786{
 787	struct tomoyo_request_info r;
 788	struct tomoyo_obj_info obj = {
 789		.path1 = *path,
 790	};
 791	int error;
 792	struct tomoyo_path_info buf;
 793	bool is_enforce;
 794	struct tomoyo_path_info symlink_target;
 795	int idx;
 796
 797	if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
 798	    == TOMOYO_CONFIG_DISABLED)
 799		return 0;
 800	is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
 801	error = -ENOMEM;
 802	buf.name = NULL;
 803	idx = tomoyo_read_lock();
 804	if (!tomoyo_get_realpath(&buf, path))
 805		goto out;
 806	r.obj = &obj;
 807	switch (operation) {
 808	case TOMOYO_TYPE_RMDIR:
 809	case TOMOYO_TYPE_CHROOT:
 810		tomoyo_add_slash(&buf);
 811		break;
 812	case TOMOYO_TYPE_SYMLINK:
 813		symlink_target.name = tomoyo_encode(target);
 814		if (!symlink_target.name)
 815			goto out;
 816		tomoyo_fill_path_info(&symlink_target);
 817		obj.symlink_target = &symlink_target;
 818		break;
 819	}
 820	error = tomoyo_path_permission(&r, operation, &buf);
 821	if (operation == TOMOYO_TYPE_SYMLINK)
 822		kfree(symlink_target.name);
 823 out:
 824	kfree(buf.name);
 825	tomoyo_read_unlock(idx);
 826	if (!is_enforce)
 827		error = 0;
 828	return error;
 829}
 830
 831/**
 832 * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
 833 *
 834 * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
 835 * @path:      Pointer to "struct path".
 836 * @mode:      Create mode.
 837 * @dev:       Device number.
 838 *
 839 * Returns 0 on success, negative value otherwise.
 840 */
 841int tomoyo_mkdev_perm(const u8 operation, struct path *path,
 842		      const unsigned int mode, unsigned int dev)
 843{
 844	struct tomoyo_request_info r;
 845	struct tomoyo_obj_info obj = {
 846		.path1 = *path,
 847	};
 848	int error = -ENOMEM;
 849	struct tomoyo_path_info buf;
 850	int idx;
 851
 852	if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
 853	    == TOMOYO_CONFIG_DISABLED)
 854		return 0;
 855	idx = tomoyo_read_lock();
 856	error = -ENOMEM;
 857	if (tomoyo_get_realpath(&buf, path)) {
 858		r.obj = &obj;
 859		dev = new_decode_dev(dev);
 860		r.param_type = TOMOYO_TYPE_MKDEV_ACL;
 861		r.param.mkdev.filename = &buf;
 862		r.param.mkdev.operation = operation;
 863		r.param.mkdev.mode = mode;
 864		r.param.mkdev.major = MAJOR(dev);
 865		r.param.mkdev.minor = MINOR(dev);
 866		tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
 867		error = tomoyo_audit_mkdev_log(&r);
 868		kfree(buf.name);
 869	}
 870	tomoyo_read_unlock(idx);
 871	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 872		error = 0;
 873	return error;
 874}
 875
 876/**
 877 * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
 878 *
 879 * @operation: Type of operation.
 880 * @path1:      Pointer to "struct path".
 881 * @path2:      Pointer to "struct path".
 882 *
 883 * Returns 0 on success, negative value otherwise.
 884 */
 885int tomoyo_path2_perm(const u8 operation, struct path *path1,
 886		      struct path *path2)
 887{
 888	int error = -ENOMEM;
 889	struct tomoyo_path_info buf1;
 890	struct tomoyo_path_info buf2;
 891	struct tomoyo_request_info r;
 892	struct tomoyo_obj_info obj = {
 893		.path1 = *path1,
 894		.path2 = *path2,
 895	};
 896	int idx;
 897
 898	if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
 899	    == TOMOYO_CONFIG_DISABLED)
 900		return 0;
 901	buf1.name = NULL;
 902	buf2.name = NULL;
 903	idx = tomoyo_read_lock();
 904	if (!tomoyo_get_realpath(&buf1, path1) ||
 905	    !tomoyo_get_realpath(&buf2, path2))
 906		goto out;
 907	switch (operation) {
 908	case TOMOYO_TYPE_RENAME:
 909	case TOMOYO_TYPE_LINK:
 910		if (!d_is_dir(path1->dentry))
 911			break;
 912		/* fall through */
 913	case TOMOYO_TYPE_PIVOT_ROOT:
 914		tomoyo_add_slash(&buf1);
 915		tomoyo_add_slash(&buf2);
 916		break;
 917	}
 918	r.obj = &obj;
 919	r.param_type = TOMOYO_TYPE_PATH2_ACL;
 920	r.param.path2.operation = operation;
 921	r.param.path2.filename1 = &buf1;
 922	r.param.path2.filename2 = &buf2;
 923	do {
 924		tomoyo_check_acl(&r, tomoyo_check_path2_acl);
 925		error = tomoyo_audit_path2_log(&r);
 926	} while (error == TOMOYO_RETRY_REQUEST);
 927 out:
 928	kfree(buf1.name);
 929	kfree(buf2.name);
 930	tomoyo_read_unlock(idx);
 931	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 932		error = 0;
 933	return error;
 934}
 935
 936/**
 937 * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
 938 *
 939 * @a: Pointer to "struct tomoyo_acl_info".
 940 * @b: Pointer to "struct tomoyo_acl_info".
 941 *
 942 * Returns true if @a == @b, false otherwise.
 943 */
 944static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
 945				  const struct tomoyo_acl_info *b)
 946{
 947	const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
 948	const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
 949	return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
 950		tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
 951		tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
 952		tomoyo_same_number_union(&p1->flags, &p2->flags);
 953}
 954
 955/**
 956 * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
 957 *
 958 * @param: Pointer to "struct tomoyo_acl_param".
 959 *
 960 * Returns 0 on success, negative value otherwise.
 961 *
 962 * Caller holds tomoyo_read_lock().
 963 */
 964static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
 965{
 966	struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
 967	int error;
 968	if (!tomoyo_parse_name_union(param, &e.dev_name) ||
 969	    !tomoyo_parse_name_union(param, &e.dir_name) ||
 970	    !tomoyo_parse_name_union(param, &e.fs_type) ||
 971	    !tomoyo_parse_number_union(param, &e.flags))
 972		error = -EINVAL;
 973	else
 974		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 975					     tomoyo_same_mount_acl, NULL);
 976	tomoyo_put_name_union(&e.dev_name);
 977	tomoyo_put_name_union(&e.dir_name);
 978	tomoyo_put_name_union(&e.fs_type);
 979	tomoyo_put_number_union(&e.flags);
 980	return error;
 981}
 982
 983/**
 984 * tomoyo_write_file - Update file related list.
 985 *
 986 * @param: Pointer to "struct tomoyo_acl_param".
 987 *
 988 * Returns 0 on success, negative value otherwise.
 989 *
 990 * Caller holds tomoyo_read_lock().
 991 */
 992int tomoyo_write_file(struct tomoyo_acl_param *param)
 993{
 994	u16 perm = 0;
 995	u8 type;
 996	const char *operation = tomoyo_read_token(param);
 997	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
 998		if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
 999			perm |= 1 << type;
1000	if (perm)
1001		return tomoyo_update_path_acl(perm, param);
1002	for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1003		if (tomoyo_permstr(operation,
1004				   tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
1005			perm |= 1 << type;
1006	if (perm)
1007		return tomoyo_update_path2_acl(perm, param);
1008	for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1009		if (tomoyo_permstr(operation,
1010				   tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
1011			perm |= 1 << type;
1012	if (perm)
1013		return tomoyo_update_path_number_acl(perm, param);
1014	for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1015		if (tomoyo_permstr(operation,
1016				   tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
1017			perm |= 1 << type;
1018	if (perm)
1019		return tomoyo_update_mkdev_acl(perm, param);
1020	if (tomoyo_permstr(operation,
1021			   tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
1022		return tomoyo_update_mount_acl(param);
1023	return -EINVAL;
1024}
v4.10.11
   1/*
   2 * security/tomoyo/file.c
   3 *
   4 * Copyright (C) 2005-2011  NTT DATA CORPORATION
   5 */
   6
   7#include "common.h"
   8#include <linux/slab.h>
   9
  10/*
  11 * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
  12 */
  13static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
  14	[TOMOYO_TYPE_EXECUTE]    = TOMOYO_MAC_FILE_EXECUTE,
  15	[TOMOYO_TYPE_READ]       = TOMOYO_MAC_FILE_OPEN,
  16	[TOMOYO_TYPE_WRITE]      = TOMOYO_MAC_FILE_OPEN,
  17	[TOMOYO_TYPE_APPEND]     = TOMOYO_MAC_FILE_OPEN,
  18	[TOMOYO_TYPE_UNLINK]     = TOMOYO_MAC_FILE_UNLINK,
  19	[TOMOYO_TYPE_GETATTR]    = TOMOYO_MAC_FILE_GETATTR,
  20	[TOMOYO_TYPE_RMDIR]      = TOMOYO_MAC_FILE_RMDIR,
  21	[TOMOYO_TYPE_TRUNCATE]   = TOMOYO_MAC_FILE_TRUNCATE,
  22	[TOMOYO_TYPE_SYMLINK]    = TOMOYO_MAC_FILE_SYMLINK,
  23	[TOMOYO_TYPE_CHROOT]     = TOMOYO_MAC_FILE_CHROOT,
  24	[TOMOYO_TYPE_UMOUNT]     = TOMOYO_MAC_FILE_UMOUNT,
  25};
  26
  27/*
  28 * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
  29 */
  30const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
  31	[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
  32	[TOMOYO_TYPE_MKCHAR]  = TOMOYO_MAC_FILE_MKCHAR,
  33};
  34
  35/*
  36 * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
  37 */
  38const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
  39	[TOMOYO_TYPE_LINK]       = TOMOYO_MAC_FILE_LINK,
  40	[TOMOYO_TYPE_RENAME]     = TOMOYO_MAC_FILE_RENAME,
  41	[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
  42};
  43
  44/*
  45 * Mapping table from "enum tomoyo_path_number_acl_index" to
  46 * "enum tomoyo_mac_index".
  47 */
  48const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
  49	[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
  50	[TOMOYO_TYPE_MKDIR]  = TOMOYO_MAC_FILE_MKDIR,
  51	[TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO,
  52	[TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK,
  53	[TOMOYO_TYPE_IOCTL]  = TOMOYO_MAC_FILE_IOCTL,
  54	[TOMOYO_TYPE_CHMOD]  = TOMOYO_MAC_FILE_CHMOD,
  55	[TOMOYO_TYPE_CHOWN]  = TOMOYO_MAC_FILE_CHOWN,
  56	[TOMOYO_TYPE_CHGRP]  = TOMOYO_MAC_FILE_CHGRP,
  57};
  58
  59/**
  60 * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
  61 *
  62 * @ptr: Pointer to "struct tomoyo_name_union".
  63 *
  64 * Returns nothing.
  65 */
  66void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
  67{
  68	tomoyo_put_group(ptr->group);
  69	tomoyo_put_name(ptr->filename);
  70}
  71
  72/**
  73 * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
  74 *
  75 * @name: Pointer to "struct tomoyo_path_info".
  76 * @ptr:  Pointer to "struct tomoyo_name_union".
  77 *
  78 * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
  79 */
  80const struct tomoyo_path_info *
  81tomoyo_compare_name_union(const struct tomoyo_path_info *name,
  82			  const struct tomoyo_name_union *ptr)
  83{
  84	if (ptr->group)
  85		return tomoyo_path_matches_group(name, ptr->group);
  86	if (tomoyo_path_matches_pattern(name, ptr->filename))
  87		return ptr->filename;
  88	return NULL;
  89}
  90
  91/**
  92 * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
  93 *
  94 * @ptr: Pointer to "struct tomoyo_number_union".
  95 *
  96 * Returns nothing.
  97 */
  98void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
  99{
 100	tomoyo_put_group(ptr->group);
 101}
 102
 103/**
 104 * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
 105 *
 106 * @value: Number to check.
 107 * @ptr:   Pointer to "struct tomoyo_number_union".
 108 *
 109 * Returns true if @value matches @ptr, false otherwise.
 110 */
 111bool tomoyo_compare_number_union(const unsigned long value,
 112				 const struct tomoyo_number_union *ptr)
 113{
 114	if (ptr->group)
 115		return tomoyo_number_matches_group(value, value, ptr->group);
 116	return value >= ptr->values[0] && value <= ptr->values[1];
 117}
 118
 119/**
 120 * tomoyo_add_slash - Add trailing '/' if needed.
 121 *
 122 * @buf: Pointer to "struct tomoyo_path_info".
 123 *
 124 * Returns nothing.
 125 *
 126 * @buf must be generated by tomoyo_encode() because this function does not
 127 * allocate memory for adding '/'.
 128 */
 129static void tomoyo_add_slash(struct tomoyo_path_info *buf)
 130{
 131	if (buf->is_dir)
 132		return;
 133	/*
 134	 * This is OK because tomoyo_encode() reserves space for appending "/".
 135	 */
 136	strcat((char *) buf->name, "/");
 137	tomoyo_fill_path_info(buf);
 138}
 139
 140/**
 141 * tomoyo_get_realpath - Get realpath.
 142 *
 143 * @buf:  Pointer to "struct tomoyo_path_info".
 144 * @path: Pointer to "struct path".
 145 *
 146 * Returns true on success, false otherwise.
 147 */
 148static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, const struct path *path)
 149{
 150	buf->name = tomoyo_realpath_from_path(path);
 151	if (buf->name) {
 152		tomoyo_fill_path_info(buf);
 153		return true;
 154	}
 155	return false;
 156}
 157
 158/**
 159 * tomoyo_audit_path_log - Audit path request log.
 160 *
 161 * @r: Pointer to "struct tomoyo_request_info".
 162 *
 163 * Returns 0 on success, negative value otherwise.
 164 */
 165static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
 166{
 167	return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
 168				 [r->param.path.operation],
 169				 r->param.path.filename->name);
 170}
 171
 172/**
 173 * tomoyo_audit_path2_log - Audit path/path request log.
 174 *
 175 * @r: Pointer to "struct tomoyo_request_info".
 176 *
 177 * Returns 0 on success, negative value otherwise.
 178 */
 179static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
 180{
 181	return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
 182				 [tomoyo_pp2mac[r->param.path2.operation]],
 183				 r->param.path2.filename1->name,
 184				 r->param.path2.filename2->name);
 185}
 186
 187/**
 188 * tomoyo_audit_mkdev_log - Audit path/number/number/number request log.
 189 *
 190 * @r: Pointer to "struct tomoyo_request_info".
 191 *
 192 * Returns 0 on success, negative value otherwise.
 193 */
 194static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
 195{
 196	return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
 197				 tomoyo_mac_keywords
 198				 [tomoyo_pnnn2mac[r->param.mkdev.operation]],
 199				 r->param.mkdev.filename->name,
 200				 r->param.mkdev.mode, r->param.mkdev.major,
 201				 r->param.mkdev.minor);
 202}
 203
 204/**
 205 * tomoyo_audit_path_number_log - Audit path/number request log.
 206 *
 207 * @r: Pointer to "struct tomoyo_request_info".
 208 *
 209 * Returns 0 on success, negative value otherwise.
 210 */
 211static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
 212{
 213	const u8 type = r->param.path_number.operation;
 214	u8 radix;
 215	char buffer[64];
 216	switch (type) {
 217	case TOMOYO_TYPE_CREATE:
 218	case TOMOYO_TYPE_MKDIR:
 219	case TOMOYO_TYPE_MKFIFO:
 220	case TOMOYO_TYPE_MKSOCK:
 221	case TOMOYO_TYPE_CHMOD:
 222		radix = TOMOYO_VALUE_TYPE_OCTAL;
 223		break;
 224	case TOMOYO_TYPE_IOCTL:
 225		radix = TOMOYO_VALUE_TYPE_HEXADECIMAL;
 226		break;
 227	default:
 228		radix = TOMOYO_VALUE_TYPE_DECIMAL;
 229		break;
 230	}
 231	tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
 232			   radix);
 233	return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
 234				 [tomoyo_pn2mac[type]],
 235				 r->param.path_number.filename->name, buffer);
 236}
 237
 238/**
 239 * tomoyo_check_path_acl - Check permission for path operation.
 240 *
 241 * @r:   Pointer to "struct tomoyo_request_info".
 242 * @ptr: Pointer to "struct tomoyo_acl_info".
 243 *
 244 * Returns true if granted, false otherwise.
 245 *
 246 * To be able to use wildcard for domain transition, this function sets
 247 * matching entry on success. Since the caller holds tomoyo_read_lock(),
 248 * it is safe to set matching entry.
 249 */
 250static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
 251				  const struct tomoyo_acl_info *ptr)
 252{
 253	const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
 254							 head);
 255	if (acl->perm & (1 << r->param.path.operation)) {
 256		r->param.path.matched_path =
 257			tomoyo_compare_name_union(r->param.path.filename,
 258						  &acl->name);
 259		return r->param.path.matched_path != NULL;
 260	}
 261	return false;
 262}
 263
 264/**
 265 * tomoyo_check_path_number_acl - Check permission for path number operation.
 266 *
 267 * @r:   Pointer to "struct tomoyo_request_info".
 268 * @ptr: Pointer to "struct tomoyo_acl_info".
 269 *
 270 * Returns true if granted, false otherwise.
 271 */
 272static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
 273					 const struct tomoyo_acl_info *ptr)
 274{
 275	const struct tomoyo_path_number_acl *acl =
 276		container_of(ptr, typeof(*acl), head);
 277	return (acl->perm & (1 << r->param.path_number.operation)) &&
 278		tomoyo_compare_number_union(r->param.path_number.number,
 279					    &acl->number) &&
 280		tomoyo_compare_name_union(r->param.path_number.filename,
 281					  &acl->name);
 282}
 283
 284/**
 285 * tomoyo_check_path2_acl - Check permission for path path operation.
 286 *
 287 * @r:   Pointer to "struct tomoyo_request_info".
 288 * @ptr: Pointer to "struct tomoyo_acl_info".
 289 *
 290 * Returns true if granted, false otherwise.
 291 */
 292static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
 293				   const struct tomoyo_acl_info *ptr)
 294{
 295	const struct tomoyo_path2_acl *acl =
 296		container_of(ptr, typeof(*acl), head);
 297	return (acl->perm & (1 << r->param.path2.operation)) &&
 298		tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
 299		&& tomoyo_compare_name_union(r->param.path2.filename2,
 300					     &acl->name2);
 301}
 302
 303/**
 304 * tomoyo_check_mkdev_acl - Check permission for path number number number operation.
 305 *
 306 * @r:   Pointer to "struct tomoyo_request_info".
 307 * @ptr: Pointer to "struct tomoyo_acl_info".
 308 *
 309 * Returns true if granted, false otherwise.
 310 */
 311static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
 312				   const struct tomoyo_acl_info *ptr)
 313{
 314	const struct tomoyo_mkdev_acl *acl =
 315		container_of(ptr, typeof(*acl), head);
 316	return (acl->perm & (1 << r->param.mkdev.operation)) &&
 317		tomoyo_compare_number_union(r->param.mkdev.mode,
 318					    &acl->mode) &&
 319		tomoyo_compare_number_union(r->param.mkdev.major,
 320					    &acl->major) &&
 321		tomoyo_compare_number_union(r->param.mkdev.minor,
 322					    &acl->minor) &&
 323		tomoyo_compare_name_union(r->param.mkdev.filename,
 324					  &acl->name);
 325}
 326
 327/**
 328 * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
 329 *
 330 * @a: Pointer to "struct tomoyo_acl_info".
 331 * @b: Pointer to "struct tomoyo_acl_info".
 332 *
 333 * Returns true if @a == @b except permission bits, false otherwise.
 334 */
 335static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
 336				 const struct tomoyo_acl_info *b)
 337{
 338	const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
 339	const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
 340	return tomoyo_same_name_union(&p1->name, &p2->name);
 341}
 342
 343/**
 344 * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry.
 345 *
 346 * @a:         Pointer to "struct tomoyo_acl_info".
 347 * @b:         Pointer to "struct tomoyo_acl_info".
 348 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 349 *
 350 * Returns true if @a is empty, false otherwise.
 351 */
 352static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
 353				  struct tomoyo_acl_info *b,
 354				  const bool is_delete)
 355{
 356	u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
 357		->perm;
 358	u16 perm = *a_perm;
 359	const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
 360	if (is_delete)
 361		perm &= ~b_perm;
 362	else
 363		perm |= b_perm;
 364	*a_perm = perm;
 365	return !perm;
 366}
 367
 368/**
 369 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
 370 *
 371 * @perm:  Permission.
 372 * @param: Pointer to "struct tomoyo_acl_param".
 373 *
 374 * Returns 0 on success, negative value otherwise.
 375 *
 376 * Caller holds tomoyo_read_lock().
 377 */
 378static int tomoyo_update_path_acl(const u16 perm,
 379				  struct tomoyo_acl_param *param)
 380{
 381	struct tomoyo_path_acl e = {
 382		.head.type = TOMOYO_TYPE_PATH_ACL,
 383		.perm = perm
 384	};
 385	int error;
 386	if (!tomoyo_parse_name_union(param, &e.name))
 387		error = -EINVAL;
 388	else
 389		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 390					     tomoyo_same_path_acl,
 391					     tomoyo_merge_path_acl);
 392	tomoyo_put_name_union(&e.name);
 393	return error;
 394}
 395
 396/**
 397 * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
 398 *
 399 * @a: Pointer to "struct tomoyo_acl_info".
 400 * @b: Pointer to "struct tomoyo_acl_info".
 401 *
 402 * Returns true if @a == @b except permission bits, false otherwise.
 403 */
 404static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
 405					 const struct tomoyo_acl_info *b)
 406{
 407	const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
 408	const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
 409	return tomoyo_same_name_union(&p1->name, &p2->name) &&
 410		tomoyo_same_number_union(&p1->mode, &p2->mode) &&
 411		tomoyo_same_number_union(&p1->major, &p2->major) &&
 412		tomoyo_same_number_union(&p1->minor, &p2->minor);
 413}
 414
 415/**
 416 * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
 417 *
 418 * @a:         Pointer to "struct tomoyo_acl_info".
 419 * @b:         Pointer to "struct tomoyo_acl_info".
 420 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 421 *
 422 * Returns true if @a is empty, false otherwise.
 423 */
 424static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
 425				   struct tomoyo_acl_info *b,
 426				   const bool is_delete)
 427{
 428	u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
 429					 head)->perm;
 430	u8 perm = *a_perm;
 431	const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
 432		->perm;
 433	if (is_delete)
 434		perm &= ~b_perm;
 435	else
 436		perm |= b_perm;
 437	*a_perm = perm;
 438	return !perm;
 439}
 440
 441/**
 442 * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
 443 *
 444 * @perm:  Permission.
 445 * @param: Pointer to "struct tomoyo_acl_param".
 446 *
 447 * Returns 0 on success, negative value otherwise.
 448 *
 449 * Caller holds tomoyo_read_lock().
 450 */
 451static int tomoyo_update_mkdev_acl(const u8 perm,
 452				   struct tomoyo_acl_param *param)
 453{
 454	struct tomoyo_mkdev_acl e = {
 455		.head.type = TOMOYO_TYPE_MKDEV_ACL,
 456		.perm = perm
 457	};
 458	int error;
 459	if (!tomoyo_parse_name_union(param, &e.name) ||
 460	    !tomoyo_parse_number_union(param, &e.mode) ||
 461	    !tomoyo_parse_number_union(param, &e.major) ||
 462	    !tomoyo_parse_number_union(param, &e.minor))
 463		error = -EINVAL;
 464	else
 465		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 466					     tomoyo_same_mkdev_acl,
 467					     tomoyo_merge_mkdev_acl);
 468	tomoyo_put_name_union(&e.name);
 469	tomoyo_put_number_union(&e.mode);
 470	tomoyo_put_number_union(&e.major);
 471	tomoyo_put_number_union(&e.minor);
 472	return error;
 473}
 474
 475/**
 476 * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
 477 *
 478 * @a: Pointer to "struct tomoyo_acl_info".
 479 * @b: Pointer to "struct tomoyo_acl_info".
 480 *
 481 * Returns true if @a == @b except permission bits, false otherwise.
 482 */
 483static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
 484				  const struct tomoyo_acl_info *b)
 485{
 486	const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
 487	const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
 488	return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
 489		tomoyo_same_name_union(&p1->name2, &p2->name2);
 490}
 491
 492/**
 493 * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
 494 *
 495 * @a:         Pointer to "struct tomoyo_acl_info".
 496 * @b:         Pointer to "struct tomoyo_acl_info".
 497 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 498 *
 499 * Returns true if @a is empty, false otherwise.
 500 */
 501static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
 502				   struct tomoyo_acl_info *b,
 503				   const bool is_delete)
 504{
 505	u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
 506		->perm;
 507	u8 perm = *a_perm;
 508	const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
 509	if (is_delete)
 510		perm &= ~b_perm;
 511	else
 512		perm |= b_perm;
 513	*a_perm = perm;
 514	return !perm;
 515}
 516
 517/**
 518 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
 519 *
 520 * @perm:  Permission.
 521 * @param: Pointer to "struct tomoyo_acl_param".
 522 *
 523 * Returns 0 on success, negative value otherwise.
 524 *
 525 * Caller holds tomoyo_read_lock().
 526 */
 527static int tomoyo_update_path2_acl(const u8 perm,
 528				   struct tomoyo_acl_param *param)
 529{
 530	struct tomoyo_path2_acl e = {
 531		.head.type = TOMOYO_TYPE_PATH2_ACL,
 532		.perm = perm
 533	};
 534	int error;
 535	if (!tomoyo_parse_name_union(param, &e.name1) ||
 536	    !tomoyo_parse_name_union(param, &e.name2))
 537		error = -EINVAL;
 538	else
 539		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 540					     tomoyo_same_path2_acl,
 541					     tomoyo_merge_path2_acl);
 542	tomoyo_put_name_union(&e.name1);
 543	tomoyo_put_name_union(&e.name2);
 544	return error;
 545}
 546
 547/**
 548 * tomoyo_path_permission - Check permission for single path operation.
 549 *
 550 * @r:         Pointer to "struct tomoyo_request_info".
 551 * @operation: Type of operation.
 552 * @filename:  Filename to check.
 553 *
 554 * Returns 0 on success, negative value otherwise.
 555 *
 556 * Caller holds tomoyo_read_lock().
 557 */
 558static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
 559				  const struct tomoyo_path_info *filename)
 560{
 561	int error;
 562
 563	r->type = tomoyo_p2mac[operation];
 564	r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
 565	if (r->mode == TOMOYO_CONFIG_DISABLED)
 566		return 0;
 567	r->param_type = TOMOYO_TYPE_PATH_ACL;
 568	r->param.path.filename = filename;
 569	r->param.path.operation = operation;
 570	do {
 571		tomoyo_check_acl(r, tomoyo_check_path_acl);
 572		error = tomoyo_audit_path_log(r);
 573	} while (error == TOMOYO_RETRY_REQUEST);
 574	return error;
 575}
 576
 577/**
 578 * tomoyo_execute_permission - Check permission for execute operation.
 579 *
 580 * @r:         Pointer to "struct tomoyo_request_info".
 581 * @filename:  Filename to check.
 582 *
 583 * Returns 0 on success, negative value otherwise.
 584 *
 585 * Caller holds tomoyo_read_lock().
 586 */
 587int tomoyo_execute_permission(struct tomoyo_request_info *r,
 588			      const struct tomoyo_path_info *filename)
 589{
 590	/*
 591	 * Unlike other permission checks, this check is done regardless of
 592	 * profile mode settings in order to check for domain transition
 593	 * preference.
 594	 */
 595	r->type = TOMOYO_MAC_FILE_EXECUTE;
 596	r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
 597	r->param_type = TOMOYO_TYPE_PATH_ACL;
 598	r->param.path.filename = filename;
 599	r->param.path.operation = TOMOYO_TYPE_EXECUTE;
 600	tomoyo_check_acl(r, tomoyo_check_path_acl);
 601	r->ee->transition = r->matched_acl && r->matched_acl->cond ?
 602		r->matched_acl->cond->transit : NULL;
 603	if (r->mode != TOMOYO_CONFIG_DISABLED)
 604		return tomoyo_audit_path_log(r);
 605	return 0;
 606}
 607
 608/**
 609 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
 610 *
 611 * @a: Pointer to "struct tomoyo_acl_info".
 612 * @b: Pointer to "struct tomoyo_acl_info".
 613 *
 614 * Returns true if @a == @b except permission bits, false otherwise.
 615 */
 616static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
 617					const struct tomoyo_acl_info *b)
 618{
 619	const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
 620							       head);
 621	const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
 622							       head);
 623	return tomoyo_same_name_union(&p1->name, &p2->name) &&
 624		tomoyo_same_number_union(&p1->number, &p2->number);
 625}
 626
 627/**
 628 * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
 629 *
 630 * @a:         Pointer to "struct tomoyo_acl_info".
 631 * @b:         Pointer to "struct tomoyo_acl_info".
 632 * @is_delete: True for @a &= ~@b, false for @a |= @b.
 633 *
 634 * Returns true if @a is empty, false otherwise.
 635 */
 636static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
 637					 struct tomoyo_acl_info *b,
 638					 const bool is_delete)
 639{
 640	u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
 641					  head)->perm;
 642	u8 perm = *a_perm;
 643	const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
 644		->perm;
 645	if (is_delete)
 646		perm &= ~b_perm;
 647	else
 648		perm |= b_perm;
 649	*a_perm = perm;
 650	return !perm;
 651}
 652
 653/**
 654 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
 655 *
 656 * @perm:  Permission.
 657 * @param: Pointer to "struct tomoyo_acl_param".
 658 *
 659 * Returns 0 on success, negative value otherwise.
 660 */
 661static int tomoyo_update_path_number_acl(const u8 perm,
 662					 struct tomoyo_acl_param *param)
 663{
 664	struct tomoyo_path_number_acl e = {
 665		.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
 666		.perm = perm
 667	};
 668	int error;
 669	if (!tomoyo_parse_name_union(param, &e.name) ||
 670	    !tomoyo_parse_number_union(param, &e.number))
 671		error = -EINVAL;
 672	else
 673		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 674					     tomoyo_same_path_number_acl,
 675					     tomoyo_merge_path_number_acl);
 676	tomoyo_put_name_union(&e.name);
 677	tomoyo_put_number_union(&e.number);
 678	return error;
 679}
 680
 681/**
 682 * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp".
 683 *
 684 * @type:   Type of operation.
 685 * @path:   Pointer to "struct path".
 686 * @number: Number.
 687 *
 688 * Returns 0 on success, negative value otherwise.
 689 */
 690int tomoyo_path_number_perm(const u8 type, const struct path *path,
 691			    unsigned long number)
 692{
 693	struct tomoyo_request_info r;
 694	struct tomoyo_obj_info obj = {
 695		.path1 = *path,
 696	};
 697	int error = -ENOMEM;
 698	struct tomoyo_path_info buf;
 699	int idx;
 700
 701	if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type])
 702	    == TOMOYO_CONFIG_DISABLED || !path->dentry)
 703		return 0;
 704	idx = tomoyo_read_lock();
 705	if (!tomoyo_get_realpath(&buf, path))
 706		goto out;
 707	r.obj = &obj;
 708	if (type == TOMOYO_TYPE_MKDIR)
 709		tomoyo_add_slash(&buf);
 710	r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL;
 711	r.param.path_number.operation = type;
 712	r.param.path_number.filename = &buf;
 713	r.param.path_number.number = number;
 714	do {
 715		tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
 716		error = tomoyo_audit_path_number_log(&r);
 717	} while (error == TOMOYO_RETRY_REQUEST);
 718	kfree(buf.name);
 719 out:
 720	tomoyo_read_unlock(idx);
 721	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 722		error = 0;
 723	return error;
 724}
 725
 726/**
 727 * tomoyo_check_open_permission - Check permission for "read" and "write".
 728 *
 729 * @domain: Pointer to "struct tomoyo_domain_info".
 730 * @path:   Pointer to "struct path".
 731 * @flag:   Flags for open().
 732 *
 733 * Returns 0 on success, negative value otherwise.
 734 */
 735int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 736				 const struct path *path, const int flag)
 737{
 738	const u8 acc_mode = ACC_MODE(flag);
 739	int error = 0;
 740	struct tomoyo_path_info buf;
 741	struct tomoyo_request_info r;
 742	struct tomoyo_obj_info obj = {
 743		.path1 = *path,
 744	};
 745	int idx;
 746
 747	buf.name = NULL;
 748	r.mode = TOMOYO_CONFIG_DISABLED;
 749	idx = tomoyo_read_lock();
 750	if (acc_mode &&
 751	    tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN)
 752	    != TOMOYO_CONFIG_DISABLED) {
 753		if (!tomoyo_get_realpath(&buf, path)) {
 754			error = -ENOMEM;
 755			goto out;
 756		}
 757		r.obj = &obj;
 758		if (acc_mode & MAY_READ)
 759			error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
 760						       &buf);
 761		if (!error && (acc_mode & MAY_WRITE))
 762			error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
 763						       TOMOYO_TYPE_APPEND :
 764						       TOMOYO_TYPE_WRITE,
 765						       &buf);
 766	}
 767 out:
 768	kfree(buf.name);
 769	tomoyo_read_unlock(idx);
 770	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 771		error = 0;
 772	return error;
 773}
 774
 775/**
 776 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount".
 777 *
 778 * @operation: Type of operation.
 779 * @path:      Pointer to "struct path".
 780 * @target:    Symlink's target if @operation is TOMOYO_TYPE_SYMLINK,
 781 *             NULL otherwise.
 782 *
 783 * Returns 0 on success, negative value otherwise.
 784 */
 785int tomoyo_path_perm(const u8 operation, const struct path *path, const char *target)
 786{
 787	struct tomoyo_request_info r;
 788	struct tomoyo_obj_info obj = {
 789		.path1 = *path,
 790	};
 791	int error;
 792	struct tomoyo_path_info buf;
 793	bool is_enforce;
 794	struct tomoyo_path_info symlink_target;
 795	int idx;
 796
 797	if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
 798	    == TOMOYO_CONFIG_DISABLED)
 799		return 0;
 800	is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
 801	error = -ENOMEM;
 802	buf.name = NULL;
 803	idx = tomoyo_read_lock();
 804	if (!tomoyo_get_realpath(&buf, path))
 805		goto out;
 806	r.obj = &obj;
 807	switch (operation) {
 808	case TOMOYO_TYPE_RMDIR:
 809	case TOMOYO_TYPE_CHROOT:
 810		tomoyo_add_slash(&buf);
 811		break;
 812	case TOMOYO_TYPE_SYMLINK:
 813		symlink_target.name = tomoyo_encode(target);
 814		if (!symlink_target.name)
 815			goto out;
 816		tomoyo_fill_path_info(&symlink_target);
 817		obj.symlink_target = &symlink_target;
 818		break;
 819	}
 820	error = tomoyo_path_permission(&r, operation, &buf);
 821	if (operation == TOMOYO_TYPE_SYMLINK)
 822		kfree(symlink_target.name);
 823 out:
 824	kfree(buf.name);
 825	tomoyo_read_unlock(idx);
 826	if (!is_enforce)
 827		error = 0;
 828	return error;
 829}
 830
 831/**
 832 * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar".
 833 *
 834 * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK)
 835 * @path:      Pointer to "struct path".
 836 * @mode:      Create mode.
 837 * @dev:       Device number.
 838 *
 839 * Returns 0 on success, negative value otherwise.
 840 */
 841int tomoyo_mkdev_perm(const u8 operation, const struct path *path,
 842		      const unsigned int mode, unsigned int dev)
 843{
 844	struct tomoyo_request_info r;
 845	struct tomoyo_obj_info obj = {
 846		.path1 = *path,
 847	};
 848	int error = -ENOMEM;
 849	struct tomoyo_path_info buf;
 850	int idx;
 851
 852	if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
 853	    == TOMOYO_CONFIG_DISABLED)
 854		return 0;
 855	idx = tomoyo_read_lock();
 856	error = -ENOMEM;
 857	if (tomoyo_get_realpath(&buf, path)) {
 858		r.obj = &obj;
 859		dev = new_decode_dev(dev);
 860		r.param_type = TOMOYO_TYPE_MKDEV_ACL;
 861		r.param.mkdev.filename = &buf;
 862		r.param.mkdev.operation = operation;
 863		r.param.mkdev.mode = mode;
 864		r.param.mkdev.major = MAJOR(dev);
 865		r.param.mkdev.minor = MINOR(dev);
 866		tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
 867		error = tomoyo_audit_mkdev_log(&r);
 868		kfree(buf.name);
 869	}
 870	tomoyo_read_unlock(idx);
 871	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 872		error = 0;
 873	return error;
 874}
 875
 876/**
 877 * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
 878 *
 879 * @operation: Type of operation.
 880 * @path1:      Pointer to "struct path".
 881 * @path2:      Pointer to "struct path".
 882 *
 883 * Returns 0 on success, negative value otherwise.
 884 */
 885int tomoyo_path2_perm(const u8 operation, const struct path *path1,
 886		      const struct path *path2)
 887{
 888	int error = -ENOMEM;
 889	struct tomoyo_path_info buf1;
 890	struct tomoyo_path_info buf2;
 891	struct tomoyo_request_info r;
 892	struct tomoyo_obj_info obj = {
 893		.path1 = *path1,
 894		.path2 = *path2,
 895	};
 896	int idx;
 897
 898	if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
 899	    == TOMOYO_CONFIG_DISABLED)
 900		return 0;
 901	buf1.name = NULL;
 902	buf2.name = NULL;
 903	idx = tomoyo_read_lock();
 904	if (!tomoyo_get_realpath(&buf1, path1) ||
 905	    !tomoyo_get_realpath(&buf2, path2))
 906		goto out;
 907	switch (operation) {
 908	case TOMOYO_TYPE_RENAME:
 909	case TOMOYO_TYPE_LINK:
 910		if (!d_is_dir(path1->dentry))
 911			break;
 912		/* fall through */
 913	case TOMOYO_TYPE_PIVOT_ROOT:
 914		tomoyo_add_slash(&buf1);
 915		tomoyo_add_slash(&buf2);
 916		break;
 917	}
 918	r.obj = &obj;
 919	r.param_type = TOMOYO_TYPE_PATH2_ACL;
 920	r.param.path2.operation = operation;
 921	r.param.path2.filename1 = &buf1;
 922	r.param.path2.filename2 = &buf2;
 923	do {
 924		tomoyo_check_acl(&r, tomoyo_check_path2_acl);
 925		error = tomoyo_audit_path2_log(&r);
 926	} while (error == TOMOYO_RETRY_REQUEST);
 927 out:
 928	kfree(buf1.name);
 929	kfree(buf2.name);
 930	tomoyo_read_unlock(idx);
 931	if (r.mode != TOMOYO_CONFIG_ENFORCING)
 932		error = 0;
 933	return error;
 934}
 935
 936/**
 937 * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
 938 *
 939 * @a: Pointer to "struct tomoyo_acl_info".
 940 * @b: Pointer to "struct tomoyo_acl_info".
 941 *
 942 * Returns true if @a == @b, false otherwise.
 943 */
 944static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
 945				  const struct tomoyo_acl_info *b)
 946{
 947	const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
 948	const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
 949	return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
 950		tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
 951		tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
 952		tomoyo_same_number_union(&p1->flags, &p2->flags);
 953}
 954
 955/**
 956 * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list.
 957 *
 958 * @param: Pointer to "struct tomoyo_acl_param".
 959 *
 960 * Returns 0 on success, negative value otherwise.
 961 *
 962 * Caller holds tomoyo_read_lock().
 963 */
 964static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
 965{
 966	struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
 967	int error;
 968	if (!tomoyo_parse_name_union(param, &e.dev_name) ||
 969	    !tomoyo_parse_name_union(param, &e.dir_name) ||
 970	    !tomoyo_parse_name_union(param, &e.fs_type) ||
 971	    !tomoyo_parse_number_union(param, &e.flags))
 972		error = -EINVAL;
 973	else
 974		error = tomoyo_update_domain(&e.head, sizeof(e), param,
 975					     tomoyo_same_mount_acl, NULL);
 976	tomoyo_put_name_union(&e.dev_name);
 977	tomoyo_put_name_union(&e.dir_name);
 978	tomoyo_put_name_union(&e.fs_type);
 979	tomoyo_put_number_union(&e.flags);
 980	return error;
 981}
 982
 983/**
 984 * tomoyo_write_file - Update file related list.
 985 *
 986 * @param: Pointer to "struct tomoyo_acl_param".
 987 *
 988 * Returns 0 on success, negative value otherwise.
 989 *
 990 * Caller holds tomoyo_read_lock().
 991 */
 992int tomoyo_write_file(struct tomoyo_acl_param *param)
 993{
 994	u16 perm = 0;
 995	u8 type;
 996	const char *operation = tomoyo_read_token(param);
 997	for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
 998		if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
 999			perm |= 1 << type;
1000	if (perm)
1001		return tomoyo_update_path_acl(perm, param);
1002	for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1003		if (tomoyo_permstr(operation,
1004				   tomoyo_mac_keywords[tomoyo_pp2mac[type]]))
1005			perm |= 1 << type;
1006	if (perm)
1007		return tomoyo_update_path2_acl(perm, param);
1008	for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1009		if (tomoyo_permstr(operation,
1010				   tomoyo_mac_keywords[tomoyo_pn2mac[type]]))
1011			perm |= 1 << type;
1012	if (perm)
1013		return tomoyo_update_path_number_acl(perm, param);
1014	for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1015		if (tomoyo_permstr(operation,
1016				   tomoyo_mac_keywords[tomoyo_pnnn2mac[type]]))
1017			perm |= 1 << type;
1018	if (perm)
1019		return tomoyo_update_mkdev_acl(perm, param);
1020	if (tomoyo_permstr(operation,
1021			   tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT]))
1022		return tomoyo_update_mount_acl(param);
1023	return -EINVAL;
1024}