cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

file.c (29925B)


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