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, 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 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 /* 574 * Do not retry for execute request, for alias may have 575 * changed. 576 */ 577 } while (error == TOMOYO_RETRY_REQUEST && 578 operation != TOMOYO_TYPE_EXECUTE); 579 return error; 580 } 581 582 /** 583 * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. 584 * 585 * @a: Pointer to "struct tomoyo_acl_info". 586 * @b: Pointer to "struct tomoyo_acl_info". 587 * 588 * Returns true if @a == @b except permission bits, false otherwise. 589 */ 590 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, 591 const struct tomoyo_acl_info *b) 592 { 593 const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), 594 head); 595 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), 596 head); 597 return tomoyo_same_name_union(&p1->name, &p2->name) && 598 tomoyo_same_number_union(&p1->number, &p2->number); 599 } 600 601 /** 602 * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry. 603 * 604 * @a: Pointer to "struct tomoyo_acl_info". 605 * @b: Pointer to "struct tomoyo_acl_info". 606 * @is_delete: True for @a &= ~@b, false for @a |= @b. 607 * 608 * Returns true if @a is empty, false otherwise. 609 */ 610 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, 611 struct tomoyo_acl_info *b, 612 const bool is_delete) 613 { 614 u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, 615 head)->perm; 616 u8 perm = *a_perm; 617 const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) 618 ->perm; 619 if (is_delete) 620 perm &= ~b_perm; 621 else 622 perm |= b_perm; 623 *a_perm = perm; 624 return !perm; 625 } 626 627 /** 628 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. 629 * 630 * @perm: Permission. 631 * @param: Pointer to "struct tomoyo_acl_param". 632 * 633 * Returns 0 on success, negative value otherwise. 634 */ 635 static int tomoyo_update_path_number_acl(const u8 perm, 636 struct tomoyo_acl_param *param) 637 { 638 struct tomoyo_path_number_acl e = { 639 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, 640 .perm = perm 641 }; 642 int error; 643 if (!tomoyo_parse_name_union(param, &e.name) || 644 !tomoyo_parse_number_union(param, &e.number)) 645 error = -EINVAL; 646 else 647 error = tomoyo_update_domain(&e.head, sizeof(e), param, 648 tomoyo_same_path_number_acl, 649 tomoyo_merge_path_number_acl); 650 tomoyo_put_name_union(&e.name); 651 tomoyo_put_number_union(&e.number); 652 return error; 653 } 654 655 /** 656 * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". 657 * 658 * @type: Type of operation. 659 * @path: Pointer to "struct path". 660 * @number: Number. 661 * 662 * Returns 0 on success, negative value otherwise. 663 */ 664 int tomoyo_path_number_perm(const u8 type, struct path *path, 665 unsigned long number) 666 { 667 struct tomoyo_request_info r; 668 struct tomoyo_obj_info obj = { 669 .path1 = *path, 670 }; 671 int error = -ENOMEM; 672 struct tomoyo_path_info buf; 673 int idx; 674 675 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) 676 == TOMOYO_CONFIG_DISABLED || !path->dentry) 677 return 0; 678 idx = tomoyo_read_lock(); 679 if (!tomoyo_get_realpath(&buf, path)) 680 goto out; 681 r.obj = &obj; 682 if (type == TOMOYO_TYPE_MKDIR) 683 tomoyo_add_slash(&buf); 684 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; 685 r.param.path_number.operation = type; 686 r.param.path_number.filename = &buf; 687 r.param.path_number.number = number; 688 do { 689 tomoyo_check_acl(&r, tomoyo_check_path_number_acl); 690 error = tomoyo_audit_path_number_log(&r); 691 } while (error == TOMOYO_RETRY_REQUEST); 692 kfree(buf.name); 693 out: 694 tomoyo_read_unlock(idx); 695 if (r.mode != TOMOYO_CONFIG_ENFORCING) 696 error = 0; 697 return error; 698 } 699 700 /** 701 * tomoyo_check_open_permission - Check permission for "read" and "write". 702 * 703 * @domain: Pointer to "struct tomoyo_domain_info". 704 * @path: Pointer to "struct path". 705 * @flag: Flags for open(). 706 * 707 * Returns 0 on success, negative value otherwise. 708 */ 709 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 710 struct path *path, const int flag) 711 { 712 const u8 acc_mode = ACC_MODE(flag); 713 int error = 0; 714 struct tomoyo_path_info buf; 715 struct tomoyo_request_info r; 716 struct tomoyo_obj_info obj = { 717 .path1 = *path, 718 }; 719 int idx; 720 721 buf.name = NULL; 722 r.mode = TOMOYO_CONFIG_DISABLED; 723 idx = tomoyo_read_lock(); 724 if (acc_mode && 725 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) 726 != TOMOYO_CONFIG_DISABLED) { 727 if (!tomoyo_get_realpath(&buf, path)) { 728 error = -ENOMEM; 729 goto out; 730 } 731 r.obj = &obj; 732 if (acc_mode & MAY_READ) 733 error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, 734 &buf); 735 if (!error && (acc_mode & MAY_WRITE)) 736 error = tomoyo_path_permission(&r, (flag & O_APPEND) ? 737 TOMOYO_TYPE_APPEND : 738 TOMOYO_TYPE_WRITE, 739 &buf); 740 } 741 out: 742 kfree(buf.name); 743 tomoyo_read_unlock(idx); 744 if (r.mode != TOMOYO_CONFIG_ENFORCING) 745 error = 0; 746 return error; 747 } 748 749 /** 750 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". 751 * 752 * @operation: Type of operation. 753 * @path: Pointer to "struct path". 754 * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK, 755 * NULL otherwise. 756 * 757 * Returns 0 on success, negative value otherwise. 758 */ 759 int tomoyo_path_perm(const u8 operation, struct path *path, const char *target) 760 { 761 struct tomoyo_request_info r; 762 struct tomoyo_obj_info obj = { 763 .path1 = *path, 764 }; 765 int error; 766 struct tomoyo_path_info buf; 767 bool is_enforce; 768 struct tomoyo_path_info symlink_target; 769 int idx; 770 771 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) 772 == TOMOYO_CONFIG_DISABLED) 773 return 0; 774 is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); 775 error = -ENOMEM; 776 buf.name = NULL; 777 idx = tomoyo_read_lock(); 778 if (!tomoyo_get_realpath(&buf, path)) 779 goto out; 780 r.obj = &obj; 781 switch (operation) { 782 case TOMOYO_TYPE_RMDIR: 783 case TOMOYO_TYPE_CHROOT: 784 tomoyo_add_slash(&buf); 785 break; 786 case TOMOYO_TYPE_SYMLINK: 787 symlink_target.name = tomoyo_encode(target); 788 if (!symlink_target.name) 789 goto out; 790 tomoyo_fill_path_info(&symlink_target); 791 obj.symlink_target = &symlink_target; 792 break; 793 } 794 error = tomoyo_path_permission(&r, operation, &buf); 795 if (operation == TOMOYO_TYPE_SYMLINK) 796 kfree(symlink_target.name); 797 out: 798 kfree(buf.name); 799 tomoyo_read_unlock(idx); 800 if (!is_enforce) 801 error = 0; 802 return error; 803 } 804 805 /** 806 * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". 807 * 808 * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) 809 * @path: Pointer to "struct path". 810 * @mode: Create mode. 811 * @dev: Device number. 812 * 813 * Returns 0 on success, negative value otherwise. 814 */ 815 int tomoyo_mkdev_perm(const u8 operation, struct path *path, 816 const unsigned int mode, unsigned int dev) 817 { 818 struct tomoyo_request_info r; 819 struct tomoyo_obj_info obj = { 820 .path1 = *path, 821 }; 822 int error = -ENOMEM; 823 struct tomoyo_path_info buf; 824 int idx; 825 826 if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) 827 == TOMOYO_CONFIG_DISABLED) 828 return 0; 829 idx = tomoyo_read_lock(); 830 error = -ENOMEM; 831 if (tomoyo_get_realpath(&buf, path)) { 832 r.obj = &obj; 833 dev = new_decode_dev(dev); 834 r.param_type = TOMOYO_TYPE_MKDEV_ACL; 835 r.param.mkdev.filename = &buf; 836 r.param.mkdev.operation = operation; 837 r.param.mkdev.mode = mode; 838 r.param.mkdev.major = MAJOR(dev); 839 r.param.mkdev.minor = MINOR(dev); 840 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); 841 error = tomoyo_audit_mkdev_log(&r); 842 kfree(buf.name); 843 } 844 tomoyo_read_unlock(idx); 845 if (r.mode != TOMOYO_CONFIG_ENFORCING) 846 error = 0; 847 return error; 848 } 849 850 /** 851 * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". 852 * 853 * @operation: Type of operation. 854 * @path1: Pointer to "struct path". 855 * @path2: Pointer to "struct path". 856 * 857 * Returns 0 on success, negative value otherwise. 858 */ 859 int tomoyo_path2_perm(const u8 operation, struct path *path1, 860 struct path *path2) 861 { 862 int error = -ENOMEM; 863 struct tomoyo_path_info buf1; 864 struct tomoyo_path_info buf2; 865 struct tomoyo_request_info r; 866 struct tomoyo_obj_info obj = { 867 .path1 = *path1, 868 .path2 = *path2, 869 }; 870 int idx; 871 872 if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) 873 == TOMOYO_CONFIG_DISABLED) 874 return 0; 875 buf1.name = NULL; 876 buf2.name = NULL; 877 idx = tomoyo_read_lock(); 878 if (!tomoyo_get_realpath(&buf1, path1) || 879 !tomoyo_get_realpath(&buf2, path2)) 880 goto out; 881 switch (operation) { 882 struct dentry *dentry; 883 case TOMOYO_TYPE_RENAME: 884 case TOMOYO_TYPE_LINK: 885 dentry = path1->dentry; 886 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) 887 break; 888 /* fall through */ 889 case TOMOYO_TYPE_PIVOT_ROOT: 890 tomoyo_add_slash(&buf1); 891 tomoyo_add_slash(&buf2); 892 break; 893 } 894 r.obj = &obj; 895 r.param_type = TOMOYO_TYPE_PATH2_ACL; 896 r.param.path2.operation = operation; 897 r.param.path2.filename1 = &buf1; 898 r.param.path2.filename2 = &buf2; 899 do { 900 tomoyo_check_acl(&r, tomoyo_check_path2_acl); 901 error = tomoyo_audit_path2_log(&r); 902 } while (error == TOMOYO_RETRY_REQUEST); 903 out: 904 kfree(buf1.name); 905 kfree(buf2.name); 906 tomoyo_read_unlock(idx); 907 if (r.mode != TOMOYO_CONFIG_ENFORCING) 908 error = 0; 909 return error; 910 } 911 912 /** 913 * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. 914 * 915 * @a: Pointer to "struct tomoyo_acl_info". 916 * @b: Pointer to "struct tomoyo_acl_info". 917 * 918 * Returns true if @a == @b, false otherwise. 919 */ 920 static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, 921 const struct tomoyo_acl_info *b) 922 { 923 const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); 924 const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); 925 return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && 926 tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && 927 tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && 928 tomoyo_same_number_union(&p1->flags, &p2->flags); 929 } 930 931 /** 932 * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list. 933 * 934 * @param: Pointer to "struct tomoyo_acl_param". 935 * 936 * Returns 0 on success, negative value otherwise. 937 * 938 * Caller holds tomoyo_read_lock(). 939 */ 940 static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) 941 { 942 struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; 943 int error; 944 if (!tomoyo_parse_name_union(param, &e.dev_name) || 945 !tomoyo_parse_name_union(param, &e.dir_name) || 946 !tomoyo_parse_name_union(param, &e.fs_type) || 947 !tomoyo_parse_number_union(param, &e.flags)) 948 error = -EINVAL; 949 else 950 error = tomoyo_update_domain(&e.head, sizeof(e), param, 951 tomoyo_same_mount_acl, NULL); 952 tomoyo_put_name_union(&e.dev_name); 953 tomoyo_put_name_union(&e.dir_name); 954 tomoyo_put_name_union(&e.fs_type); 955 tomoyo_put_number_union(&e.flags); 956 return error; 957 } 958 959 /** 960 * tomoyo_write_file - Update file related list. 961 * 962 * @param: Pointer to "struct tomoyo_acl_param". 963 * 964 * Returns 0 on success, negative value otherwise. 965 * 966 * Caller holds tomoyo_read_lock(). 967 */ 968 int tomoyo_write_file(struct tomoyo_acl_param *param) 969 { 970 u16 perm = 0; 971 u8 type; 972 const char *operation = tomoyo_read_token(param); 973 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) 974 if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) 975 perm |= 1 << type; 976 if (perm) 977 return tomoyo_update_path_acl(perm, param); 978 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) 979 if (tomoyo_permstr(operation, 980 tomoyo_mac_keywords[tomoyo_pp2mac[type]])) 981 perm |= 1 << type; 982 if (perm) 983 return tomoyo_update_path2_acl(perm, param); 984 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) 985 if (tomoyo_permstr(operation, 986 tomoyo_mac_keywords[tomoyo_pn2mac[type]])) 987 perm |= 1 << type; 988 if (perm) 989 return tomoyo_update_path_number_acl(perm, param); 990 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) 991 if (tomoyo_permstr(operation, 992 tomoyo_mac_keywords[tomoyo_pnnn2mac[type]])) 993 perm |= 1 << type; 994 if (perm) 995 return tomoyo_update_mkdev_acl(perm, param); 996 if (tomoyo_permstr(operation, 997 tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT])) 998 return tomoyo_update_mount_acl(param); 999 return -EINVAL; 1000 } 1001