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