1b69a54eeSKentaro Takeda /* 2b69a54eeSKentaro Takeda * security/tomoyo/file.c 3b69a54eeSKentaro Takeda * 4c3ef1500STetsuo Handa * Pathname restriction functions. 5b69a54eeSKentaro Takeda * 6c3ef1500STetsuo Handa * Copyright (C) 2005-2010 NTT DATA CORPORATION 7b69a54eeSKentaro Takeda */ 8b69a54eeSKentaro Takeda 9b69a54eeSKentaro Takeda #include "common.h" 105a0e3ad6STejun Heo #include <linux/slab.h> 11b69a54eeSKentaro Takeda 12a1f9bb6aSTetsuo Handa /* Keyword array for operations with one pathname. */ 1371c28236STetsuo Handa const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 147ef61233STetsuo Handa [TOMOYO_TYPE_EXECUTE] = "execute", 157ef61233STetsuo Handa [TOMOYO_TYPE_READ] = "read", 167ef61233STetsuo Handa [TOMOYO_TYPE_WRITE] = "write", 177c75964fSTetsuo Handa [TOMOYO_TYPE_APPEND] = "append", 187ef61233STetsuo Handa [TOMOYO_TYPE_UNLINK] = "unlink", 197c75964fSTetsuo Handa [TOMOYO_TYPE_GETATTR] = "getattr", 207ef61233STetsuo Handa [TOMOYO_TYPE_RMDIR] = "rmdir", 217ef61233STetsuo Handa [TOMOYO_TYPE_TRUNCATE] = "truncate", 227ef61233STetsuo Handa [TOMOYO_TYPE_SYMLINK] = "symlink", 237ef61233STetsuo Handa [TOMOYO_TYPE_CHROOT] = "chroot", 247ef61233STetsuo Handa [TOMOYO_TYPE_UMOUNT] = "unmount", 25b69a54eeSKentaro Takeda }; 26b69a54eeSKentaro Takeda 27a1f9bb6aSTetsuo Handa /* Keyword array for operations with one pathname and three numbers. */ 2871c28236STetsuo Handa const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = { 29a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_MKBLOCK] = "mkblock", 30a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_MKCHAR] = "mkchar", 31a1f9bb6aSTetsuo Handa }; 32a1f9bb6aSTetsuo Handa 33a1f9bb6aSTetsuo Handa /* Keyword array for operations with two pathnames. */ 3471c28236STetsuo Handa const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { 357ef61233STetsuo Handa [TOMOYO_TYPE_LINK] = "link", 367ef61233STetsuo Handa [TOMOYO_TYPE_RENAME] = "rename", 377ef61233STetsuo Handa [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 38b69a54eeSKentaro Takeda }; 39b69a54eeSKentaro Takeda 40a1f9bb6aSTetsuo Handa /* Keyword array for operations with one pathname and one number. */ 4171c28236STetsuo Handa const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 42a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_CREATE] = "create", 43a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_MKDIR] = "mkdir", 44a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_MKFIFO] = "mkfifo", 45a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_MKSOCK] = "mksock", 46a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_IOCTL] = "ioctl", 47a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_CHMOD] = "chmod", 48a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_CHOWN] = "chown", 49a1f9bb6aSTetsuo Handa [TOMOYO_TYPE_CHGRP] = "chgrp", 50a1f9bb6aSTetsuo Handa }; 51a1f9bb6aSTetsuo Handa 520df7e8b8STetsuo Handa /* 530df7e8b8STetsuo Handa * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index". 540df7e8b8STetsuo Handa */ 5557c2590fSTetsuo Handa static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { 5657c2590fSTetsuo Handa [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, 5757c2590fSTetsuo Handa [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, 5857c2590fSTetsuo Handa [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, 597c75964fSTetsuo Handa [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN, 6057c2590fSTetsuo Handa [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, 617c75964fSTetsuo Handa [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR, 6257c2590fSTetsuo Handa [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, 6357c2590fSTetsuo Handa [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, 6457c2590fSTetsuo Handa [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, 6557c2590fSTetsuo Handa [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, 6657c2590fSTetsuo Handa [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, 6757c2590fSTetsuo Handa }; 6857c2590fSTetsuo Handa 690df7e8b8STetsuo Handa /* 700df7e8b8STetsuo Handa * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index". 710df7e8b8STetsuo Handa */ 7275093152STetsuo Handa static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { 7357c2590fSTetsuo Handa [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, 7457c2590fSTetsuo Handa [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, 7557c2590fSTetsuo Handa }; 7657c2590fSTetsuo Handa 770df7e8b8STetsuo Handa /* 780df7e8b8STetsuo Handa * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index". 790df7e8b8STetsuo Handa */ 8057c2590fSTetsuo Handa static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { 8157c2590fSTetsuo Handa [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, 8257c2590fSTetsuo Handa [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, 8357c2590fSTetsuo Handa [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, 8457c2590fSTetsuo Handa }; 8557c2590fSTetsuo Handa 860df7e8b8STetsuo Handa /* 870df7e8b8STetsuo Handa * Mapping table from "enum tomoyo_path_number_acl_index" to 880df7e8b8STetsuo Handa * "enum tomoyo_mac_index". 890df7e8b8STetsuo Handa */ 9057c2590fSTetsuo Handa static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 9157c2590fSTetsuo Handa [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, 9257c2590fSTetsuo Handa [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, 9357c2590fSTetsuo Handa [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, 9457c2590fSTetsuo Handa [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, 9557c2590fSTetsuo Handa [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, 9657c2590fSTetsuo Handa [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, 9757c2590fSTetsuo Handa [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, 9857c2590fSTetsuo Handa [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, 9957c2590fSTetsuo Handa }; 10057c2590fSTetsuo Handa 1010df7e8b8STetsuo Handa /** 1020df7e8b8STetsuo Handa * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union". 1030df7e8b8STetsuo Handa * 1040df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_name_union". 1050df7e8b8STetsuo Handa * 1060df7e8b8STetsuo Handa * Returns nothing. 1070df7e8b8STetsuo Handa */ 1087762fbffSTetsuo Handa void tomoyo_put_name_union(struct tomoyo_name_union *ptr) 1097762fbffSTetsuo Handa { 110a98aa4deSTetsuo Handa tomoyo_put_group(ptr->group); 1117762fbffSTetsuo Handa tomoyo_put_name(ptr->filename); 1127762fbffSTetsuo Handa } 1137762fbffSTetsuo Handa 1140df7e8b8STetsuo Handa /** 1150df7e8b8STetsuo Handa * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not. 1160df7e8b8STetsuo Handa * 1170df7e8b8STetsuo Handa * @name: Pointer to "struct tomoyo_path_info". 1180df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_name_union". 1190df7e8b8STetsuo Handa * 1200df7e8b8STetsuo Handa * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise. 1210df7e8b8STetsuo Handa */ 122484ca79cSTetsuo Handa const struct tomoyo_path_info * 123484ca79cSTetsuo Handa tomoyo_compare_name_union(const struct tomoyo_path_info *name, 1247762fbffSTetsuo Handa const struct tomoyo_name_union *ptr) 1257762fbffSTetsuo Handa { 1260df7e8b8STetsuo Handa if (ptr->group) 1273f629636STetsuo Handa return tomoyo_path_matches_group(name, ptr->group); 128484ca79cSTetsuo Handa if (tomoyo_path_matches_pattern(name, ptr->filename)) 129484ca79cSTetsuo Handa return ptr->filename; 130484ca79cSTetsuo Handa return NULL; 1317762fbffSTetsuo Handa } 1327762fbffSTetsuo Handa 1330df7e8b8STetsuo Handa /** 1340df7e8b8STetsuo Handa * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union". 1350df7e8b8STetsuo Handa * 1360df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_number_union". 1370df7e8b8STetsuo Handa * 1380df7e8b8STetsuo Handa * Returns nothing. 1390df7e8b8STetsuo Handa */ 1404c3e9e2dSTetsuo Handa void tomoyo_put_number_union(struct tomoyo_number_union *ptr) 1414c3e9e2dSTetsuo Handa { 142a98aa4deSTetsuo Handa tomoyo_put_group(ptr->group); 1434c3e9e2dSTetsuo Handa } 1444c3e9e2dSTetsuo Handa 1450df7e8b8STetsuo Handa /** 1460df7e8b8STetsuo Handa * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not. 1470df7e8b8STetsuo Handa * 1480df7e8b8STetsuo Handa * @value: Number to check. 1490df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_number_union". 1500df7e8b8STetsuo Handa * 1510df7e8b8STetsuo Handa * Returns true if @value matches @ptr, false otherwise. 1520df7e8b8STetsuo Handa */ 1534c3e9e2dSTetsuo Handa bool tomoyo_compare_number_union(const unsigned long value, 1544c3e9e2dSTetsuo Handa const struct tomoyo_number_union *ptr) 1554c3e9e2dSTetsuo Handa { 1560df7e8b8STetsuo Handa if (ptr->group) 1574c3e9e2dSTetsuo Handa return tomoyo_number_matches_group(value, value, ptr->group); 1584c3e9e2dSTetsuo Handa return value >= ptr->values[0] && value <= ptr->values[1]; 1594c3e9e2dSTetsuo Handa } 1604c3e9e2dSTetsuo Handa 1610df7e8b8STetsuo Handa /** 1620df7e8b8STetsuo Handa * tomoyo_add_slash - Add trailing '/' if needed. 1630df7e8b8STetsuo Handa * 1640df7e8b8STetsuo Handa * @buf: Pointer to "struct tomoyo_path_info". 1650df7e8b8STetsuo Handa * 1660df7e8b8STetsuo Handa * Returns nothing. 1670df7e8b8STetsuo Handa * 1680df7e8b8STetsuo Handa * @buf must be generated by tomoyo_encode() because this function does not 1690df7e8b8STetsuo Handa * allocate memory for adding '/'. 1700df7e8b8STetsuo Handa */ 171c8c57e84STetsuo Handa static void tomoyo_add_slash(struct tomoyo_path_info *buf) 172c8c57e84STetsuo Handa { 173c8c57e84STetsuo Handa if (buf->is_dir) 174c8c57e84STetsuo Handa return; 175c8c57e84STetsuo Handa /* 176c8c57e84STetsuo Handa * This is OK because tomoyo_encode() reserves space for appending "/". 177c8c57e84STetsuo Handa */ 178c8c57e84STetsuo Handa strcat((char *) buf->name, "/"); 179c8c57e84STetsuo Handa tomoyo_fill_path_info(buf); 180c8c57e84STetsuo Handa } 181c8c57e84STetsuo Handa 182a1f9bb6aSTetsuo Handa /** 183c8c57e84STetsuo Handa * tomoyo_get_realpath - Get realpath. 184b69a54eeSKentaro Takeda * 185c8c57e84STetsuo Handa * @buf: Pointer to "struct tomoyo_path_info". 186b69a54eeSKentaro Takeda * @path: Pointer to "struct path". 187b69a54eeSKentaro Takeda * 188c8c57e84STetsuo Handa * Returns true on success, false otherwise. 189b69a54eeSKentaro Takeda */ 190c8c57e84STetsuo Handa static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) 191b69a54eeSKentaro Takeda { 192c8c57e84STetsuo Handa buf->name = tomoyo_realpath_from_path(path); 193c8c57e84STetsuo Handa if (buf->name) { 194c8c57e84STetsuo Handa tomoyo_fill_path_info(buf); 195c8c57e84STetsuo Handa return true; 196b69a54eeSKentaro Takeda } 197c8c57e84STetsuo Handa return false; 198b69a54eeSKentaro Takeda } 199b69a54eeSKentaro Takeda 20099a85259STetsuo Handa /** 20199a85259STetsuo Handa * tomoyo_audit_path_log - Audit path request log. 20299a85259STetsuo Handa * 20399a85259STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 20499a85259STetsuo Handa * 20599a85259STetsuo Handa * Returns 0 on success, negative value otherwise. 20699a85259STetsuo Handa */ 20799a85259STetsuo Handa static int tomoyo_audit_path_log(struct tomoyo_request_info *r) 20899a85259STetsuo Handa { 20999a85259STetsuo Handa const char *operation = tomoyo_path_keyword[r->param.path.operation]; 21099a85259STetsuo Handa const struct tomoyo_path_info *filename = r->param.path.filename; 21199a85259STetsuo Handa if (r->granted) 21299a85259STetsuo Handa return 0; 21399a85259STetsuo Handa tomoyo_warn_log(r, "%s %s", operation, filename->name); 21499a85259STetsuo Handa return tomoyo_supervisor(r, "allow_%s %s\n", operation, 2157c75964fSTetsuo Handa filename->name); 21699a85259STetsuo Handa } 21799a85259STetsuo Handa 21899a85259STetsuo Handa /** 21999a85259STetsuo Handa * tomoyo_audit_path2_log - Audit path/path request log. 22099a85259STetsuo Handa * 22199a85259STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 22299a85259STetsuo Handa * 22399a85259STetsuo Handa * Returns 0 on success, negative value otherwise. 22499a85259STetsuo Handa */ 22599a85259STetsuo Handa static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) 22699a85259STetsuo Handa { 22799a85259STetsuo Handa const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; 22899a85259STetsuo Handa const struct tomoyo_path_info *filename1 = r->param.path2.filename1; 22999a85259STetsuo Handa const struct tomoyo_path_info *filename2 = r->param.path2.filename2; 23099a85259STetsuo Handa if (r->granted) 23199a85259STetsuo Handa return 0; 23299a85259STetsuo Handa tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, 23399a85259STetsuo Handa filename2->name); 23499a85259STetsuo Handa return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 2357c75964fSTetsuo Handa filename1->name, filename2->name); 23699a85259STetsuo Handa } 23799a85259STetsuo Handa 23899a85259STetsuo Handa /** 23999a85259STetsuo Handa * tomoyo_audit_mkdev_log - Audit path/number/number/number request log. 24099a85259STetsuo Handa * 24199a85259STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 24299a85259STetsuo Handa * 24399a85259STetsuo Handa * Returns 0 on success, negative value otherwise. 24499a85259STetsuo Handa */ 24599a85259STetsuo Handa static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) 24699a85259STetsuo Handa { 24771c28236STetsuo Handa const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation]; 24899a85259STetsuo Handa const struct tomoyo_path_info *filename = r->param.mkdev.filename; 24999a85259STetsuo Handa const unsigned int major = r->param.mkdev.major; 25099a85259STetsuo Handa const unsigned int minor = r->param.mkdev.minor; 25199a85259STetsuo Handa const unsigned int mode = r->param.mkdev.mode; 25299a85259STetsuo Handa if (r->granted) 25399a85259STetsuo Handa return 0; 25499a85259STetsuo Handa tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, 25599a85259STetsuo Handa major, minor); 25699a85259STetsuo Handa return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, 2577c75964fSTetsuo Handa filename->name, mode, major, minor); 25899a85259STetsuo Handa } 25999a85259STetsuo Handa 26099a85259STetsuo Handa /** 26199a85259STetsuo Handa * tomoyo_audit_path_number_log - Audit path/number request log. 26299a85259STetsuo Handa * 26399a85259STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 26499a85259STetsuo Handa * 26599a85259STetsuo Handa * Returns 0 on success, negative value otherwise. 26699a85259STetsuo Handa */ 26799a85259STetsuo Handa static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) 26899a85259STetsuo Handa { 26999a85259STetsuo Handa const u8 type = r->param.path_number.operation; 27099a85259STetsuo Handa u8 radix; 27199a85259STetsuo Handa const struct tomoyo_path_info *filename = r->param.path_number.filename; 27299a85259STetsuo Handa const char *operation = tomoyo_path_number_keyword[type]; 27399a85259STetsuo Handa char buffer[64]; 27499a85259STetsuo Handa if (r->granted) 27599a85259STetsuo Handa return 0; 27699a85259STetsuo Handa switch (type) { 27799a85259STetsuo Handa case TOMOYO_TYPE_CREATE: 27899a85259STetsuo Handa case TOMOYO_TYPE_MKDIR: 27999a85259STetsuo Handa case TOMOYO_TYPE_MKFIFO: 28099a85259STetsuo Handa case TOMOYO_TYPE_MKSOCK: 28199a85259STetsuo Handa case TOMOYO_TYPE_CHMOD: 28299a85259STetsuo Handa radix = TOMOYO_VALUE_TYPE_OCTAL; 28399a85259STetsuo Handa break; 28499a85259STetsuo Handa case TOMOYO_TYPE_IOCTL: 28599a85259STetsuo Handa radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; 28699a85259STetsuo Handa break; 28799a85259STetsuo Handa default: 28899a85259STetsuo Handa radix = TOMOYO_VALUE_TYPE_DECIMAL; 28999a85259STetsuo Handa break; 29099a85259STetsuo Handa } 29199a85259STetsuo Handa tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, 29299a85259STetsuo Handa radix); 29399a85259STetsuo Handa tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); 29499a85259STetsuo Handa return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 2957c75964fSTetsuo Handa filename->name, buffer); 296b69a54eeSKentaro Takeda } 297b69a54eeSKentaro Takeda 2980df7e8b8STetsuo Handa /** 2990df7e8b8STetsuo Handa * tomoyo_check_path_acl - Check permission for path operation. 3000df7e8b8STetsuo Handa * 3010df7e8b8STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 3020df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_acl_info". 3030df7e8b8STetsuo Handa * 3040df7e8b8STetsuo Handa * Returns true if granted, false otherwise. 3050df7e8b8STetsuo Handa * 3060df7e8b8STetsuo Handa * To be able to use wildcard for domain transition, this function sets 3070df7e8b8STetsuo Handa * matching entry on success. Since the caller holds tomoyo_read_lock(), 3080df7e8b8STetsuo Handa * it is safe to set matching entry. 3090df7e8b8STetsuo Handa */ 310484ca79cSTetsuo Handa static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, 31199a85259STetsuo Handa const struct tomoyo_acl_info *ptr) 312b69a54eeSKentaro Takeda { 31399a85259STetsuo Handa const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), 31499a85259STetsuo Handa head); 315484ca79cSTetsuo Handa if (acl->perm & (1 << r->param.path.operation)) { 316484ca79cSTetsuo Handa r->param.path.matched_path = 317484ca79cSTetsuo Handa tomoyo_compare_name_union(r->param.path.filename, 318484ca79cSTetsuo Handa &acl->name); 319484ca79cSTetsuo Handa return r->param.path.matched_path != NULL; 320484ca79cSTetsuo Handa } 321484ca79cSTetsuo Handa return false; 322b69a54eeSKentaro Takeda } 32399a85259STetsuo Handa 3240df7e8b8STetsuo Handa /** 3250df7e8b8STetsuo Handa * tomoyo_check_path_number_acl - Check permission for path number operation. 3260df7e8b8STetsuo Handa * 3270df7e8b8STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 3280df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_acl_info". 3290df7e8b8STetsuo Handa * 3300df7e8b8STetsuo Handa * Returns true if granted, false otherwise. 3310df7e8b8STetsuo Handa */ 332484ca79cSTetsuo Handa static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, 33399a85259STetsuo Handa const struct tomoyo_acl_info *ptr) 33499a85259STetsuo Handa { 33599a85259STetsuo Handa const struct tomoyo_path_number_acl *acl = 33699a85259STetsuo Handa container_of(ptr, typeof(*acl), head); 33799a85259STetsuo Handa return (acl->perm & (1 << r->param.path_number.operation)) && 33899a85259STetsuo Handa tomoyo_compare_number_union(r->param.path_number.number, 33999a85259STetsuo Handa &acl->number) && 34099a85259STetsuo Handa tomoyo_compare_name_union(r->param.path_number.filename, 34199a85259STetsuo Handa &acl->name); 34299a85259STetsuo Handa } 34399a85259STetsuo Handa 3440df7e8b8STetsuo Handa /** 3450df7e8b8STetsuo Handa * tomoyo_check_path2_acl - Check permission for path path operation. 3460df7e8b8STetsuo Handa * 3470df7e8b8STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 3480df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_acl_info". 3490df7e8b8STetsuo Handa * 3500df7e8b8STetsuo Handa * Returns true if granted, false otherwise. 3510df7e8b8STetsuo Handa */ 352484ca79cSTetsuo Handa static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, 35399a85259STetsuo Handa const struct tomoyo_acl_info *ptr) 35499a85259STetsuo Handa { 35599a85259STetsuo Handa const struct tomoyo_path2_acl *acl = 35699a85259STetsuo Handa container_of(ptr, typeof(*acl), head); 35799a85259STetsuo Handa return (acl->perm & (1 << r->param.path2.operation)) && 35899a85259STetsuo Handa tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) 35999a85259STetsuo Handa && tomoyo_compare_name_union(r->param.path2.filename2, 36099a85259STetsuo Handa &acl->name2); 36199a85259STetsuo Handa } 36299a85259STetsuo Handa 3630df7e8b8STetsuo Handa /** 3640df7e8b8STetsuo Handa * tomoyo_check_mkdev_acl - Check permission for path number number number operation. 3650df7e8b8STetsuo Handa * 3660df7e8b8STetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 3670df7e8b8STetsuo Handa * @ptr: Pointer to "struct tomoyo_acl_info". 3680df7e8b8STetsuo Handa * 3690df7e8b8STetsuo Handa * Returns true if granted, false otherwise. 3700df7e8b8STetsuo Handa */ 371484ca79cSTetsuo Handa static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, 37299a85259STetsuo Handa const struct tomoyo_acl_info *ptr) 37399a85259STetsuo Handa { 37475093152STetsuo Handa const struct tomoyo_mkdev_acl *acl = 37599a85259STetsuo Handa container_of(ptr, typeof(*acl), head); 37699a85259STetsuo Handa return (acl->perm & (1 << r->param.mkdev.operation)) && 37799a85259STetsuo Handa tomoyo_compare_number_union(r->param.mkdev.mode, 37899a85259STetsuo Handa &acl->mode) && 37999a85259STetsuo Handa tomoyo_compare_number_union(r->param.mkdev.major, 38099a85259STetsuo Handa &acl->major) && 38199a85259STetsuo Handa tomoyo_compare_number_union(r->param.mkdev.minor, 38299a85259STetsuo Handa &acl->minor) && 38399a85259STetsuo Handa tomoyo_compare_name_union(r->param.mkdev.filename, 38499a85259STetsuo Handa &acl->name); 385b69a54eeSKentaro Takeda } 386b69a54eeSKentaro Takeda 3870df7e8b8STetsuo Handa /** 3880df7e8b8STetsuo Handa * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry. 3890df7e8b8STetsuo Handa * 3900df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 3910df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 3920df7e8b8STetsuo Handa * 3930df7e8b8STetsuo Handa * Returns true if @a == @b except permission bits, false otherwise. 3940df7e8b8STetsuo Handa */ 395237ab459STetsuo Handa static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, 396237ab459STetsuo Handa const struct tomoyo_acl_info *b) 397237ab459STetsuo Handa { 398237ab459STetsuo Handa const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); 399237ab459STetsuo Handa const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); 4000df7e8b8STetsuo Handa return tomoyo_same_name_union(&p1->name, &p2->name); 401237ab459STetsuo Handa } 402237ab459STetsuo Handa 4037c75964fSTetsuo Handa /** 4047c75964fSTetsuo Handa * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry. 4057c75964fSTetsuo Handa * 4067c75964fSTetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 4077c75964fSTetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 4087c75964fSTetsuo Handa * @is_delete: True for @a &= ~@b, false for @a |= @b. 4097c75964fSTetsuo Handa * 4107c75964fSTetsuo Handa * Returns true if @a is empty, false otherwise. 4117c75964fSTetsuo Handa */ 412237ab459STetsuo Handa static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, 413237ab459STetsuo Handa struct tomoyo_acl_info *b, 414237ab459STetsuo Handa const bool is_delete) 415237ab459STetsuo Handa { 416237ab459STetsuo Handa u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) 417237ab459STetsuo Handa ->perm; 418237ab459STetsuo Handa u16 perm = *a_perm; 419237ab459STetsuo Handa const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; 4207c75964fSTetsuo Handa if (is_delete) 421237ab459STetsuo Handa perm &= ~b_perm; 4227c75964fSTetsuo Handa else 423237ab459STetsuo Handa perm |= b_perm; 424237ab459STetsuo Handa *a_perm = perm; 425237ab459STetsuo Handa return !perm; 426237ab459STetsuo Handa } 427237ab459STetsuo Handa 428b69a54eeSKentaro Takeda /** 4297ef61233STetsuo Handa * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. 430b69a54eeSKentaro Takeda * 431a238cf5bSTetsuo Handa * @perm: Permission. 432a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 433b69a54eeSKentaro Takeda * 434b69a54eeSKentaro Takeda * Returns 0 on success, negative value otherwise. 435fdb8ebb7STetsuo Handa * 436fdb8ebb7STetsuo Handa * Caller holds tomoyo_read_lock(). 437b69a54eeSKentaro Takeda */ 438a238cf5bSTetsuo Handa static int tomoyo_update_path_acl(const u16 perm, 439a238cf5bSTetsuo Handa struct tomoyo_acl_param *param) 440b69a54eeSKentaro Takeda { 4419e4b50e9STetsuo Handa struct tomoyo_path_acl e = { 4429e4b50e9STetsuo Handa .head.type = TOMOYO_TYPE_PATH_ACL, 443a238cf5bSTetsuo Handa .perm = perm 4449e4b50e9STetsuo Handa }; 445237ab459STetsuo Handa int error; 446a238cf5bSTetsuo Handa if (!tomoyo_parse_name_union(param, &e.name)) 447a238cf5bSTetsuo Handa error = -EINVAL; 448a238cf5bSTetsuo Handa else 449a238cf5bSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 450237ab459STetsuo Handa tomoyo_same_path_acl, 451237ab459STetsuo Handa tomoyo_merge_path_acl); 4527762fbffSTetsuo Handa tomoyo_put_name_union(&e.name); 453b69a54eeSKentaro Takeda return error; 454b69a54eeSKentaro Takeda } 455b69a54eeSKentaro Takeda 4560df7e8b8STetsuo Handa /** 4570df7e8b8STetsuo Handa * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry. 4580df7e8b8STetsuo Handa * 4590df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 4600df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 4610df7e8b8STetsuo Handa * 4620df7e8b8STetsuo Handa * Returns true if @a == @b except permission bits, false otherwise. 4630df7e8b8STetsuo Handa */ 46475093152STetsuo Handa static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, 465237ab459STetsuo Handa const struct tomoyo_acl_info *b) 466237ab459STetsuo Handa { 4670df7e8b8STetsuo Handa const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); 4680df7e8b8STetsuo Handa const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); 4690df7e8b8STetsuo Handa return tomoyo_same_name_union(&p1->name, &p2->name) && 4700df7e8b8STetsuo Handa tomoyo_same_number_union(&p1->mode, &p2->mode) && 4710df7e8b8STetsuo Handa tomoyo_same_number_union(&p1->major, &p2->major) && 4720df7e8b8STetsuo Handa tomoyo_same_number_union(&p1->minor, &p2->minor); 473237ab459STetsuo Handa } 474237ab459STetsuo Handa 4750df7e8b8STetsuo Handa /** 4760df7e8b8STetsuo Handa * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry. 4770df7e8b8STetsuo Handa * 4780df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 4790df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 4800df7e8b8STetsuo Handa * @is_delete: True for @a &= ~@b, false for @a |= @b. 4810df7e8b8STetsuo Handa * 4820df7e8b8STetsuo Handa * Returns true if @a is empty, false otherwise. 4830df7e8b8STetsuo Handa */ 48475093152STetsuo Handa static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, 485237ab459STetsuo Handa struct tomoyo_acl_info *b, 486237ab459STetsuo Handa const bool is_delete) 487237ab459STetsuo Handa { 48875093152STetsuo Handa u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, 489237ab459STetsuo Handa head)->perm; 490237ab459STetsuo Handa u8 perm = *a_perm; 49175093152STetsuo Handa const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) 492237ab459STetsuo Handa ->perm; 493237ab459STetsuo Handa if (is_delete) 494237ab459STetsuo Handa perm &= ~b_perm; 495237ab459STetsuo Handa else 496237ab459STetsuo Handa perm |= b_perm; 497237ab459STetsuo Handa *a_perm = perm; 498237ab459STetsuo Handa return !perm; 499237ab459STetsuo Handa } 500237ab459STetsuo Handa 501b69a54eeSKentaro Takeda /** 50275093152STetsuo Handa * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. 503a1f9bb6aSTetsuo Handa * 504a238cf5bSTetsuo Handa * @perm: Permission. 505a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 506a1f9bb6aSTetsuo Handa * 507a1f9bb6aSTetsuo Handa * Returns 0 on success, negative value otherwise. 508237ab459STetsuo Handa * 509237ab459STetsuo Handa * Caller holds tomoyo_read_lock(). 510a1f9bb6aSTetsuo Handa */ 511a238cf5bSTetsuo Handa static int tomoyo_update_mkdev_acl(const u8 perm, 512a238cf5bSTetsuo Handa struct tomoyo_acl_param *param) 513a1f9bb6aSTetsuo Handa { 51475093152STetsuo Handa struct tomoyo_mkdev_acl e = { 51575093152STetsuo Handa .head.type = TOMOYO_TYPE_MKDEV_ACL, 516a238cf5bSTetsuo Handa .perm = perm 517a1f9bb6aSTetsuo Handa }; 518a238cf5bSTetsuo Handa int error; 519a238cf5bSTetsuo Handa if (!tomoyo_parse_name_union(param, &e.name) || 520a238cf5bSTetsuo Handa !tomoyo_parse_number_union(param, &e.mode) || 521a238cf5bSTetsuo Handa !tomoyo_parse_number_union(param, &e.major) || 522a238cf5bSTetsuo Handa !tomoyo_parse_number_union(param, &e.minor)) 523a238cf5bSTetsuo Handa error = -EINVAL; 524a238cf5bSTetsuo Handa else 525a238cf5bSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 52675093152STetsuo Handa tomoyo_same_mkdev_acl, 52775093152STetsuo Handa tomoyo_merge_mkdev_acl); 528a1f9bb6aSTetsuo Handa tomoyo_put_name_union(&e.name); 529a1f9bb6aSTetsuo Handa tomoyo_put_number_union(&e.mode); 530a1f9bb6aSTetsuo Handa tomoyo_put_number_union(&e.major); 531a1f9bb6aSTetsuo Handa tomoyo_put_number_union(&e.minor); 532a1f9bb6aSTetsuo Handa return error; 533a1f9bb6aSTetsuo Handa } 534a1f9bb6aSTetsuo Handa 5350df7e8b8STetsuo Handa /** 5360df7e8b8STetsuo Handa * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry. 5370df7e8b8STetsuo Handa * 5380df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 5390df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 5400df7e8b8STetsuo Handa * 5410df7e8b8STetsuo Handa * Returns true if @a == @b except permission bits, false otherwise. 5420df7e8b8STetsuo Handa */ 543237ab459STetsuo Handa static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, 544237ab459STetsuo Handa const struct tomoyo_acl_info *b) 545237ab459STetsuo Handa { 546237ab459STetsuo Handa const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); 547237ab459STetsuo Handa const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); 5480df7e8b8STetsuo Handa return tomoyo_same_name_union(&p1->name1, &p2->name1) && 5490df7e8b8STetsuo Handa tomoyo_same_name_union(&p1->name2, &p2->name2); 550237ab459STetsuo Handa } 551237ab459STetsuo Handa 5520df7e8b8STetsuo Handa /** 5530df7e8b8STetsuo Handa * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry. 5540df7e8b8STetsuo Handa * 5550df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 5560df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 5570df7e8b8STetsuo Handa * @is_delete: True for @a &= ~@b, false for @a |= @b. 5580df7e8b8STetsuo Handa * 5590df7e8b8STetsuo Handa * Returns true if @a is empty, false otherwise. 5600df7e8b8STetsuo Handa */ 561237ab459STetsuo Handa static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, 562237ab459STetsuo Handa struct tomoyo_acl_info *b, 563237ab459STetsuo Handa const bool is_delete) 564237ab459STetsuo Handa { 565237ab459STetsuo Handa u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) 566237ab459STetsuo Handa ->perm; 567237ab459STetsuo Handa u8 perm = *a_perm; 568237ab459STetsuo Handa const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; 569237ab459STetsuo Handa if (is_delete) 570237ab459STetsuo Handa perm &= ~b_perm; 571237ab459STetsuo Handa else 572237ab459STetsuo Handa perm |= b_perm; 573237ab459STetsuo Handa *a_perm = perm; 574237ab459STetsuo Handa return !perm; 575237ab459STetsuo Handa } 576237ab459STetsuo Handa 577a1f9bb6aSTetsuo Handa /** 5787ef61233STetsuo Handa * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. 579b69a54eeSKentaro Takeda * 580a238cf5bSTetsuo Handa * @perm: Permission. 581a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 582b69a54eeSKentaro Takeda * 583b69a54eeSKentaro Takeda * Returns 0 on success, negative value otherwise. 584fdb8ebb7STetsuo Handa * 585fdb8ebb7STetsuo Handa * Caller holds tomoyo_read_lock(). 586b69a54eeSKentaro Takeda */ 587a238cf5bSTetsuo Handa static int tomoyo_update_path2_acl(const u8 perm, 588a238cf5bSTetsuo Handa struct tomoyo_acl_param *param) 589b69a54eeSKentaro Takeda { 5909e4b50e9STetsuo Handa struct tomoyo_path2_acl e = { 5919e4b50e9STetsuo Handa .head.type = TOMOYO_TYPE_PATH2_ACL, 592a238cf5bSTetsuo Handa .perm = perm 5939e4b50e9STetsuo Handa }; 594a238cf5bSTetsuo Handa int error; 595a238cf5bSTetsuo Handa if (!tomoyo_parse_name_union(param, &e.name1) || 596a238cf5bSTetsuo Handa !tomoyo_parse_name_union(param, &e.name2)) 597a238cf5bSTetsuo Handa error = -EINVAL; 598a238cf5bSTetsuo Handa else 599a238cf5bSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 600237ab459STetsuo Handa tomoyo_same_path2_acl, 601237ab459STetsuo Handa tomoyo_merge_path2_acl); 6027762fbffSTetsuo Handa tomoyo_put_name_union(&e.name1); 6037762fbffSTetsuo Handa tomoyo_put_name_union(&e.name2); 604b69a54eeSKentaro Takeda return error; 605b69a54eeSKentaro Takeda } 606b69a54eeSKentaro Takeda 607b69a54eeSKentaro Takeda /** 608cb0abe6aSTetsuo Handa * tomoyo_path_permission - Check permission for single path operation. 609b69a54eeSKentaro Takeda * 610cb0abe6aSTetsuo Handa * @r: Pointer to "struct tomoyo_request_info". 611b69a54eeSKentaro Takeda * @operation: Type of operation. 612b69a54eeSKentaro Takeda * @filename: Filename to check. 613b69a54eeSKentaro Takeda * 614b69a54eeSKentaro Takeda * Returns 0 on success, negative value otherwise. 615fdb8ebb7STetsuo Handa * 616fdb8ebb7STetsuo Handa * Caller holds tomoyo_read_lock(). 617b69a54eeSKentaro Takeda */ 61805336deeSTetsuo Handa int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 619cb0abe6aSTetsuo Handa const struct tomoyo_path_info *filename) 620b69a54eeSKentaro Takeda { 621b69a54eeSKentaro Takeda int error; 622b69a54eeSKentaro Takeda 62357c2590fSTetsuo Handa r->type = tomoyo_p2mac[operation]; 62457c2590fSTetsuo Handa r->mode = tomoyo_get_mode(r->profile, r->type); 62557c2590fSTetsuo Handa if (r->mode == TOMOYO_CONFIG_DISABLED) 62657c2590fSTetsuo Handa return 0; 627cf6e9a64STetsuo Handa r->param_type = TOMOYO_TYPE_PATH_ACL; 628cf6e9a64STetsuo Handa r->param.path.filename = filename; 629cf6e9a64STetsuo Handa r->param.path.operation = operation; 63017fcfbd9STetsuo Handa do { 63199a85259STetsuo Handa tomoyo_check_acl(r, tomoyo_check_path_acl); 63299a85259STetsuo Handa error = tomoyo_audit_path_log(r); 63305336deeSTetsuo Handa /* 63405336deeSTetsuo Handa * Do not retry for execute request, for alias may have 63505336deeSTetsuo Handa * changed. 63605336deeSTetsuo Handa */ 63705336deeSTetsuo Handa } while (error == TOMOYO_RETRY_REQUEST && 63805336deeSTetsuo Handa operation != TOMOYO_TYPE_EXECUTE); 639b69a54eeSKentaro Takeda return error; 640b69a54eeSKentaro Takeda } 641b69a54eeSKentaro Takeda 6420df7e8b8STetsuo Handa /** 6430df7e8b8STetsuo Handa * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. 6440df7e8b8STetsuo Handa * 6450df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 6460df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 6470df7e8b8STetsuo Handa * 6480df7e8b8STetsuo Handa * Returns true if @a == @b except permission bits, false otherwise. 6490df7e8b8STetsuo Handa */ 650237ab459STetsuo Handa static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, 651237ab459STetsuo Handa const struct tomoyo_acl_info *b) 652237ab459STetsuo Handa { 653237ab459STetsuo Handa const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), 654237ab459STetsuo Handa head); 655237ab459STetsuo Handa const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), 656237ab459STetsuo Handa head); 6570df7e8b8STetsuo Handa return tomoyo_same_name_union(&p1->name, &p2->name) && 6580df7e8b8STetsuo Handa tomoyo_same_number_union(&p1->number, &p2->number); 659237ab459STetsuo Handa } 660237ab459STetsuo Handa 6610df7e8b8STetsuo Handa /** 6620df7e8b8STetsuo Handa * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry. 6630df7e8b8STetsuo Handa * 6640df7e8b8STetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 6650df7e8b8STetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 6660df7e8b8STetsuo Handa * @is_delete: True for @a &= ~@b, false for @a |= @b. 6670df7e8b8STetsuo Handa * 6680df7e8b8STetsuo Handa * Returns true if @a is empty, false otherwise. 6690df7e8b8STetsuo Handa */ 670237ab459STetsuo Handa static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, 671237ab459STetsuo Handa struct tomoyo_acl_info *b, 672237ab459STetsuo Handa const bool is_delete) 673237ab459STetsuo Handa { 674237ab459STetsuo Handa u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, 675237ab459STetsuo Handa head)->perm; 676237ab459STetsuo Handa u8 perm = *a_perm; 677237ab459STetsuo Handa const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) 678237ab459STetsuo Handa ->perm; 679237ab459STetsuo Handa if (is_delete) 680237ab459STetsuo Handa perm &= ~b_perm; 681237ab459STetsuo Handa else 682237ab459STetsuo Handa perm |= b_perm; 683237ab459STetsuo Handa *a_perm = perm; 684237ab459STetsuo Handa return !perm; 685237ab459STetsuo Handa } 686237ab459STetsuo Handa 687a1f9bb6aSTetsuo Handa /** 688a1f9bb6aSTetsuo Handa * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. 689a1f9bb6aSTetsuo Handa * 690a238cf5bSTetsuo Handa * @perm: Permission. 691a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 692a1f9bb6aSTetsuo Handa * 693a1f9bb6aSTetsuo Handa * Returns 0 on success, negative value otherwise. 694a1f9bb6aSTetsuo Handa */ 695a238cf5bSTetsuo Handa static int tomoyo_update_path_number_acl(const u8 perm, 696a238cf5bSTetsuo Handa struct tomoyo_acl_param *param) 697a1f9bb6aSTetsuo Handa { 698a1f9bb6aSTetsuo Handa struct tomoyo_path_number_acl e = { 699a1f9bb6aSTetsuo Handa .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, 700a238cf5bSTetsuo Handa .perm = perm 701a1f9bb6aSTetsuo Handa }; 702a238cf5bSTetsuo Handa int error; 703a238cf5bSTetsuo Handa if (!tomoyo_parse_name_union(param, &e.name) || 704a238cf5bSTetsuo Handa !tomoyo_parse_number_union(param, &e.number)) 705a238cf5bSTetsuo Handa error = -EINVAL; 706a238cf5bSTetsuo Handa else 707a238cf5bSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 708237ab459STetsuo Handa tomoyo_same_path_number_acl, 709237ab459STetsuo Handa tomoyo_merge_path_number_acl); 710a1f9bb6aSTetsuo Handa tomoyo_put_name_union(&e.name); 711a1f9bb6aSTetsuo Handa tomoyo_put_number_union(&e.number); 712a1f9bb6aSTetsuo Handa return error; 713a1f9bb6aSTetsuo Handa } 714a1f9bb6aSTetsuo Handa 715a1f9bb6aSTetsuo Handa /** 716a1f9bb6aSTetsuo Handa * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". 717a1f9bb6aSTetsuo Handa * 718a1f9bb6aSTetsuo Handa * @type: Type of operation. 719a1f9bb6aSTetsuo Handa * @path: Pointer to "struct path". 720a1f9bb6aSTetsuo Handa * @number: Number. 721a1f9bb6aSTetsuo Handa * 722a1f9bb6aSTetsuo Handa * Returns 0 on success, negative value otherwise. 723a1f9bb6aSTetsuo Handa */ 724a1f9bb6aSTetsuo Handa int tomoyo_path_number_perm(const u8 type, struct path *path, 725a1f9bb6aSTetsuo Handa unsigned long number) 726a1f9bb6aSTetsuo Handa { 727a1f9bb6aSTetsuo Handa struct tomoyo_request_info r; 728a1f9bb6aSTetsuo Handa int error = -ENOMEM; 729c8c57e84STetsuo Handa struct tomoyo_path_info buf; 730a1f9bb6aSTetsuo Handa int idx; 731a1f9bb6aSTetsuo Handa 73257c2590fSTetsuo Handa if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) 73357c2590fSTetsuo Handa == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) 734a1f9bb6aSTetsuo Handa return 0; 735a1f9bb6aSTetsuo Handa idx = tomoyo_read_lock(); 736c8c57e84STetsuo Handa if (!tomoyo_get_realpath(&buf, path)) 737a1f9bb6aSTetsuo Handa goto out; 738c8c57e84STetsuo Handa if (type == TOMOYO_TYPE_MKDIR) 739c8c57e84STetsuo Handa tomoyo_add_slash(&buf); 740cb917cf5STetsuo Handa r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; 741cb917cf5STetsuo Handa r.param.path_number.operation = type; 742cb917cf5STetsuo Handa r.param.path_number.filename = &buf; 743cb917cf5STetsuo Handa r.param.path_number.number = number; 744cb917cf5STetsuo Handa do { 745cb917cf5STetsuo Handa tomoyo_check_acl(&r, tomoyo_check_path_number_acl); 746cb917cf5STetsuo Handa error = tomoyo_audit_path_number_log(&r); 747cb917cf5STetsuo Handa } while (error == TOMOYO_RETRY_REQUEST); 748c8c57e84STetsuo Handa kfree(buf.name); 749cb917cf5STetsuo Handa out: 750a1f9bb6aSTetsuo Handa tomoyo_read_unlock(idx); 751a1f9bb6aSTetsuo Handa if (r.mode != TOMOYO_CONFIG_ENFORCING) 752a1f9bb6aSTetsuo Handa error = 0; 753a1f9bb6aSTetsuo Handa return error; 754a1f9bb6aSTetsuo Handa } 755a1f9bb6aSTetsuo Handa 756a1f9bb6aSTetsuo Handa /** 757b69a54eeSKentaro Takeda * tomoyo_check_open_permission - Check permission for "read" and "write". 758b69a54eeSKentaro Takeda * 759b69a54eeSKentaro Takeda * @domain: Pointer to "struct tomoyo_domain_info". 760b69a54eeSKentaro Takeda * @path: Pointer to "struct path". 761b69a54eeSKentaro Takeda * @flag: Flags for open(). 762b69a54eeSKentaro Takeda * 763b69a54eeSKentaro Takeda * Returns 0 on success, negative value otherwise. 764b69a54eeSKentaro Takeda */ 765b69a54eeSKentaro Takeda int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 766b69a54eeSKentaro Takeda struct path *path, const int flag) 767b69a54eeSKentaro Takeda { 768b69a54eeSKentaro Takeda const u8 acc_mode = ACC_MODE(flag); 769eae61f3cSTetsuo Handa int error = 0; 770c8c57e84STetsuo Handa struct tomoyo_path_info buf; 771cb0abe6aSTetsuo Handa struct tomoyo_request_info r; 772fdb8ebb7STetsuo Handa int idx; 773b69a54eeSKentaro Takeda 7747c75964fSTetsuo Handa if (!path->mnt) 775b69a54eeSKentaro Takeda return 0; 77657c2590fSTetsuo Handa buf.name = NULL; 77757c2590fSTetsuo Handa r.mode = TOMOYO_CONFIG_DISABLED; 778fdb8ebb7STetsuo Handa idx = tomoyo_read_lock(); 7797c75964fSTetsuo Handa if (acc_mode && 7807c75964fSTetsuo Handa tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) 78157c2590fSTetsuo Handa != TOMOYO_CONFIG_DISABLED) { 78257c2590fSTetsuo Handa if (!tomoyo_get_realpath(&buf, path)) { 78357c2590fSTetsuo Handa error = -ENOMEM; 78457c2590fSTetsuo Handa goto out; 785b69a54eeSKentaro Takeda } 7867c75964fSTetsuo Handa if (acc_mode & MAY_READ) 7877c75964fSTetsuo Handa error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, 78857c2590fSTetsuo Handa &buf); 7897c75964fSTetsuo Handa if (!error && (acc_mode & MAY_WRITE)) 7907c75964fSTetsuo Handa error = tomoyo_path_permission(&r, (flag & O_APPEND) ? 7917c75964fSTetsuo Handa TOMOYO_TYPE_APPEND : 7927c75964fSTetsuo Handa TOMOYO_TYPE_WRITE, 7937c75964fSTetsuo Handa &buf); 79457c2590fSTetsuo Handa } 795b69a54eeSKentaro Takeda out: 796c8c57e84STetsuo Handa kfree(buf.name); 797fdb8ebb7STetsuo Handa tomoyo_read_unlock(idx); 798cb0abe6aSTetsuo Handa if (r.mode != TOMOYO_CONFIG_ENFORCING) 799b69a54eeSKentaro Takeda error = 0; 800b69a54eeSKentaro Takeda return error; 801b69a54eeSKentaro Takeda } 802b69a54eeSKentaro Takeda 803b69a54eeSKentaro Takeda /** 8047c75964fSTetsuo Handa * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". 805b69a54eeSKentaro Takeda * 806b69a54eeSKentaro Takeda * @operation: Type of operation. 807b69a54eeSKentaro Takeda * @path: Pointer to "struct path". 808b69a54eeSKentaro Takeda * 809b69a54eeSKentaro Takeda * Returns 0 on success, negative value otherwise. 810b69a54eeSKentaro Takeda */ 81197d6931eSTetsuo Handa int tomoyo_path_perm(const u8 operation, struct path *path) 812b69a54eeSKentaro Takeda { 813cb0abe6aSTetsuo Handa struct tomoyo_request_info r; 8147c75964fSTetsuo Handa int error; 8157c75964fSTetsuo Handa struct tomoyo_path_info buf; 8167c75964fSTetsuo Handa bool is_enforce; 817fdb8ebb7STetsuo Handa int idx; 818b69a54eeSKentaro Takeda 81957c2590fSTetsuo Handa if (!path->mnt) 820b69a54eeSKentaro Takeda return 0; 82157c2590fSTetsuo Handa if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) 82257c2590fSTetsuo Handa == TOMOYO_CONFIG_DISABLED) 82357c2590fSTetsuo Handa return 0; 8247c75964fSTetsuo Handa is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); 8257c75964fSTetsuo Handa error = -ENOMEM; 82657c2590fSTetsuo Handa buf.name = NULL; 827fdb8ebb7STetsuo Handa idx = tomoyo_read_lock(); 828c8c57e84STetsuo Handa if (!tomoyo_get_realpath(&buf, path)) 829b69a54eeSKentaro Takeda goto out; 830b69a54eeSKentaro Takeda switch (operation) { 8317ef61233STetsuo Handa case TOMOYO_TYPE_RMDIR: 8327ef61233STetsuo Handa case TOMOYO_TYPE_CHROOT: 833c8c57e84STetsuo Handa tomoyo_add_slash(&buf); 834c8c57e84STetsuo Handa break; 835b69a54eeSKentaro Takeda } 836c8c57e84STetsuo Handa error = tomoyo_path_permission(&r, operation, &buf); 837b69a54eeSKentaro Takeda out: 838c8c57e84STetsuo Handa kfree(buf.name); 839fdb8ebb7STetsuo Handa tomoyo_read_unlock(idx); 8407c75964fSTetsuo Handa if (!is_enforce) 841b69a54eeSKentaro Takeda error = 0; 842b69a54eeSKentaro Takeda return error; 843b69a54eeSKentaro Takeda } 844b69a54eeSKentaro Takeda 845b69a54eeSKentaro Takeda /** 84675093152STetsuo Handa * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". 847a1f9bb6aSTetsuo Handa * 848a1f9bb6aSTetsuo Handa * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) 849a1f9bb6aSTetsuo Handa * @path: Pointer to "struct path". 850a1f9bb6aSTetsuo Handa * @mode: Create mode. 851a1f9bb6aSTetsuo Handa * @dev: Device number. 852a1f9bb6aSTetsuo Handa * 853a1f9bb6aSTetsuo Handa * Returns 0 on success, negative value otherwise. 854a1f9bb6aSTetsuo Handa */ 85575093152STetsuo Handa int tomoyo_mkdev_perm(const u8 operation, struct path *path, 856a1f9bb6aSTetsuo Handa const unsigned int mode, unsigned int dev) 857a1f9bb6aSTetsuo Handa { 858a1f9bb6aSTetsuo Handa struct tomoyo_request_info r; 859a1f9bb6aSTetsuo Handa int error = -ENOMEM; 860c8c57e84STetsuo Handa struct tomoyo_path_info buf; 861a1f9bb6aSTetsuo Handa int idx; 862a1f9bb6aSTetsuo Handa 86357c2590fSTetsuo Handa if (!path->mnt || 86457c2590fSTetsuo Handa tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) 86557c2590fSTetsuo Handa == TOMOYO_CONFIG_DISABLED) 866a1f9bb6aSTetsuo Handa return 0; 867a1f9bb6aSTetsuo Handa idx = tomoyo_read_lock(); 868a1f9bb6aSTetsuo Handa error = -ENOMEM; 869c8c57e84STetsuo Handa if (tomoyo_get_realpath(&buf, path)) { 870cf6e9a64STetsuo Handa dev = new_decode_dev(dev); 87175093152STetsuo Handa r.param_type = TOMOYO_TYPE_MKDEV_ACL; 872cf6e9a64STetsuo Handa r.param.mkdev.filename = &buf; 873cf6e9a64STetsuo Handa r.param.mkdev.operation = operation; 874cf6e9a64STetsuo Handa r.param.mkdev.mode = mode; 875cf6e9a64STetsuo Handa r.param.mkdev.major = MAJOR(dev); 876cf6e9a64STetsuo Handa r.param.mkdev.minor = MINOR(dev); 87799a85259STetsuo Handa tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); 87899a85259STetsuo Handa error = tomoyo_audit_mkdev_log(&r); 879c8c57e84STetsuo Handa kfree(buf.name); 880a1f9bb6aSTetsuo Handa } 881a1f9bb6aSTetsuo Handa tomoyo_read_unlock(idx); 882a1f9bb6aSTetsuo Handa if (r.mode != TOMOYO_CONFIG_ENFORCING) 883a1f9bb6aSTetsuo Handa error = 0; 884a1f9bb6aSTetsuo Handa return error; 885a1f9bb6aSTetsuo Handa } 886a1f9bb6aSTetsuo Handa 887a1f9bb6aSTetsuo Handa /** 8887ef61233STetsuo Handa * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". 889b69a54eeSKentaro Takeda * 890b69a54eeSKentaro Takeda * @operation: Type of operation. 891b69a54eeSKentaro Takeda * @path1: Pointer to "struct path". 892b69a54eeSKentaro Takeda * @path2: Pointer to "struct path". 893b69a54eeSKentaro Takeda * 894b69a54eeSKentaro Takeda * Returns 0 on success, negative value otherwise. 895b69a54eeSKentaro Takeda */ 89697d6931eSTetsuo Handa int tomoyo_path2_perm(const u8 operation, struct path *path1, 897b69a54eeSKentaro Takeda struct path *path2) 898b69a54eeSKentaro Takeda { 899b69a54eeSKentaro Takeda int error = -ENOMEM; 900c8c57e84STetsuo Handa struct tomoyo_path_info buf1; 901c8c57e84STetsuo Handa struct tomoyo_path_info buf2; 902cb0abe6aSTetsuo Handa struct tomoyo_request_info r; 903fdb8ebb7STetsuo Handa int idx; 904b69a54eeSKentaro Takeda 90557c2590fSTetsuo Handa if (!path1->mnt || !path2->mnt || 90657c2590fSTetsuo Handa tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) 90757c2590fSTetsuo Handa == TOMOYO_CONFIG_DISABLED) 908b69a54eeSKentaro Takeda return 0; 909c8c57e84STetsuo Handa buf1.name = NULL; 910c8c57e84STetsuo Handa buf2.name = NULL; 911fdb8ebb7STetsuo Handa idx = tomoyo_read_lock(); 912c8c57e84STetsuo Handa if (!tomoyo_get_realpath(&buf1, path1) || 913c8c57e84STetsuo Handa !tomoyo_get_realpath(&buf2, path2)) 914b69a54eeSKentaro Takeda goto out; 91557c2590fSTetsuo Handa switch (operation) { 91657c2590fSTetsuo Handa struct dentry *dentry; 91757c2590fSTetsuo Handa case TOMOYO_TYPE_RENAME: 91857c2590fSTetsuo Handa case TOMOYO_TYPE_LINK: 91957c2590fSTetsuo Handa dentry = path1->dentry; 92057c2590fSTetsuo Handa if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) 92157c2590fSTetsuo Handa break; 92257c2590fSTetsuo Handa /* fall through */ 92357c2590fSTetsuo Handa case TOMOYO_TYPE_PIVOT_ROOT: 924c8c57e84STetsuo Handa tomoyo_add_slash(&buf1); 925c8c57e84STetsuo Handa tomoyo_add_slash(&buf2); 92657c2590fSTetsuo Handa break; 927b69a54eeSKentaro Takeda } 928cf6e9a64STetsuo Handa r.param_type = TOMOYO_TYPE_PATH2_ACL; 929cf6e9a64STetsuo Handa r.param.path2.operation = operation; 930cf6e9a64STetsuo Handa r.param.path2.filename1 = &buf1; 931cf6e9a64STetsuo Handa r.param.path2.filename2 = &buf2; 93217fcfbd9STetsuo Handa do { 93399a85259STetsuo Handa tomoyo_check_acl(&r, tomoyo_check_path2_acl); 93499a85259STetsuo Handa error = tomoyo_audit_path2_log(&r); 93517fcfbd9STetsuo Handa } while (error == TOMOYO_RETRY_REQUEST); 936b69a54eeSKentaro Takeda out: 937c8c57e84STetsuo Handa kfree(buf1.name); 938c8c57e84STetsuo Handa kfree(buf2.name); 939fdb8ebb7STetsuo Handa tomoyo_read_unlock(idx); 940cb0abe6aSTetsuo Handa if (r.mode != TOMOYO_CONFIG_ENFORCING) 941b69a54eeSKentaro Takeda error = 0; 942b69a54eeSKentaro Takeda return error; 943b69a54eeSKentaro Takeda } 944a1f9bb6aSTetsuo Handa 945a1f9bb6aSTetsuo Handa /** 946a238cf5bSTetsuo Handa * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. 947a1f9bb6aSTetsuo Handa * 948a238cf5bSTetsuo Handa * @a: Pointer to "struct tomoyo_acl_info". 949a238cf5bSTetsuo Handa * @b: Pointer to "struct tomoyo_acl_info". 950a238cf5bSTetsuo Handa * 951a238cf5bSTetsuo Handa * Returns true if @a == @b, false otherwise. 952a238cf5bSTetsuo Handa */ 953a238cf5bSTetsuo Handa static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, 954a238cf5bSTetsuo Handa const struct tomoyo_acl_info *b) 955a238cf5bSTetsuo Handa { 956a238cf5bSTetsuo Handa const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); 957a238cf5bSTetsuo Handa const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); 958a238cf5bSTetsuo Handa return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && 959a238cf5bSTetsuo Handa tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && 960a238cf5bSTetsuo Handa tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && 961a238cf5bSTetsuo Handa tomoyo_same_number_union(&p1->flags, &p2->flags); 962a238cf5bSTetsuo Handa } 963a238cf5bSTetsuo Handa 964a238cf5bSTetsuo Handa /** 965a238cf5bSTetsuo Handa * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list. 966a238cf5bSTetsuo Handa * 967a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 968a1f9bb6aSTetsuo Handa * 969a1f9bb6aSTetsuo Handa * Returns 0 on success, negative value otherwise. 970a1f9bb6aSTetsuo Handa * 971a1f9bb6aSTetsuo Handa * Caller holds tomoyo_read_lock(). 972a1f9bb6aSTetsuo Handa */ 973a238cf5bSTetsuo Handa static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) 974a1f9bb6aSTetsuo Handa { 975a238cf5bSTetsuo Handa struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; 976a238cf5bSTetsuo Handa int error; 977a238cf5bSTetsuo Handa if (!tomoyo_parse_name_union(param, &e.dev_name) || 978a238cf5bSTetsuo Handa !tomoyo_parse_name_union(param, &e.dir_name) || 979a238cf5bSTetsuo Handa !tomoyo_parse_name_union(param, &e.fs_type) || 980a238cf5bSTetsuo Handa !tomoyo_parse_number_union(param, &e.flags)) 981a238cf5bSTetsuo Handa error = -EINVAL; 982a238cf5bSTetsuo Handa else 983a238cf5bSTetsuo Handa error = tomoyo_update_domain(&e.head, sizeof(e), param, 984a238cf5bSTetsuo Handa tomoyo_same_mount_acl, NULL); 985a238cf5bSTetsuo Handa tomoyo_put_name_union(&e.dev_name); 986a238cf5bSTetsuo Handa tomoyo_put_name_union(&e.dir_name); 987a238cf5bSTetsuo Handa tomoyo_put_name_union(&e.fs_type); 988a238cf5bSTetsuo Handa tomoyo_put_number_union(&e.flags); 989a238cf5bSTetsuo Handa return error; 990a238cf5bSTetsuo Handa } 991a238cf5bSTetsuo Handa 992a238cf5bSTetsuo Handa /** 993a238cf5bSTetsuo Handa * tomoyo_write_file - Update file related list. 994a238cf5bSTetsuo Handa * 995a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param". 996a238cf5bSTetsuo Handa * 997a238cf5bSTetsuo Handa * Returns 0 on success, negative value otherwise. 998a238cf5bSTetsuo Handa * 999a238cf5bSTetsuo Handa * Caller holds tomoyo_read_lock(). 1000a238cf5bSTetsuo Handa */ 1001a238cf5bSTetsuo Handa int tomoyo_write_file(struct tomoyo_acl_param *param) 1002a238cf5bSTetsuo Handa { 1003a238cf5bSTetsuo Handa u16 perm = 0; 1004a1f9bb6aSTetsuo Handa u8 type; 1005a238cf5bSTetsuo Handa const char *operation = tomoyo_read_token(param); 1006a238cf5bSTetsuo Handa for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) 1007a238cf5bSTetsuo Handa if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) 1008a238cf5bSTetsuo Handa perm |= 1 << type; 1009a238cf5bSTetsuo Handa if (perm) 1010a238cf5bSTetsuo Handa return tomoyo_update_path_acl(perm, param); 1011a238cf5bSTetsuo Handa for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) 1012a238cf5bSTetsuo Handa if (tomoyo_permstr(operation, tomoyo_path2_keyword[type])) 1013a238cf5bSTetsuo Handa perm |= 1 << type; 1014a238cf5bSTetsuo Handa if (perm) 1015a238cf5bSTetsuo Handa return tomoyo_update_path2_acl(perm, param); 1016a238cf5bSTetsuo Handa for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) 1017a238cf5bSTetsuo Handa if (tomoyo_permstr(operation, 1018a238cf5bSTetsuo Handa tomoyo_path_number_keyword[type])) 1019a238cf5bSTetsuo Handa perm |= 1 << type; 1020a238cf5bSTetsuo Handa if (perm) 1021a238cf5bSTetsuo Handa return tomoyo_update_path_number_acl(perm, param); 1022a238cf5bSTetsuo Handa for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) 1023a238cf5bSTetsuo Handa if (tomoyo_permstr(operation, tomoyo_mkdev_keyword[type])) 1024a238cf5bSTetsuo Handa perm |= 1 << type; 1025a238cf5bSTetsuo Handa if (perm) 1026a238cf5bSTetsuo Handa return tomoyo_update_mkdev_acl(perm, param); 1027a238cf5bSTetsuo Handa if (tomoyo_permstr(operation, "mount")) 1028a238cf5bSTetsuo Handa return tomoyo_update_mount_acl(param); 1029a1f9bb6aSTetsuo Handa return -EINVAL; 1030a1f9bb6aSTetsuo Handa } 1031