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