file.c revision 31845e8c6d3f4f26702e567c667277f9fd1f73a3
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/* Keyword array for operations with one pathname. */ 13const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 14 [TOMOYO_TYPE_READ_WRITE] = "read/write", 15 [TOMOYO_TYPE_EXECUTE] = "execute", 16 [TOMOYO_TYPE_READ] = "read", 17 [TOMOYO_TYPE_WRITE] = "write", 18 [TOMOYO_TYPE_UNLINK] = "unlink", 19 [TOMOYO_TYPE_RMDIR] = "rmdir", 20 [TOMOYO_TYPE_TRUNCATE] = "truncate", 21 [TOMOYO_TYPE_SYMLINK] = "symlink", 22 [TOMOYO_TYPE_REWRITE] = "rewrite", 23 [TOMOYO_TYPE_CHROOT] = "chroot", 24 [TOMOYO_TYPE_UMOUNT] = "unmount", 25}; 26 27/* Keyword array for operations with one pathname and three numbers. */ 28const char *tomoyo_mkdev_keyword[TOMOYO_MAX_MKDEV_OPERATION] = { 29 [TOMOYO_TYPE_MKBLOCK] = "mkblock", 30 [TOMOYO_TYPE_MKCHAR] = "mkchar", 31}; 32 33/* Keyword array for operations with two pathnames. */ 34const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { 35 [TOMOYO_TYPE_LINK] = "link", 36 [TOMOYO_TYPE_RENAME] = "rename", 37 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", 38}; 39 40/* Keyword array for operations with one pathname and one number. */ 41const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 42 [TOMOYO_TYPE_CREATE] = "create", 43 [TOMOYO_TYPE_MKDIR] = "mkdir", 44 [TOMOYO_TYPE_MKFIFO] = "mkfifo", 45 [TOMOYO_TYPE_MKSOCK] = "mksock", 46 [TOMOYO_TYPE_IOCTL] = "ioctl", 47 [TOMOYO_TYPE_CHMOD] = "chmod", 48 [TOMOYO_TYPE_CHOWN] = "chown", 49 [TOMOYO_TYPE_CHGRP] = "chgrp", 50}; 51 52static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { 53 [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, 54 [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, 55 [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, 56 [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, 57 [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, 58 [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, 59 [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, 60 [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, 61 [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE, 62 [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, 63 [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, 64}; 65 66static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { 67 [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, 68 [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, 69}; 70 71static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { 72 [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, 73 [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, 74 [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, 75}; 76 77static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { 78 [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, 79 [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, 80 [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, 81 [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, 82 [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, 83 [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, 84 [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, 85 [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, 86}; 87 88void tomoyo_put_name_union(struct tomoyo_name_union *ptr) 89{ 90 if (!ptr) 91 return; 92 if (ptr->is_group) 93 tomoyo_put_group(ptr->group); 94 else 95 tomoyo_put_name(ptr->filename); 96} 97 98bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, 99 const struct tomoyo_name_union *ptr) 100{ 101 if (ptr->is_group) 102 return tomoyo_path_matches_group(name, ptr->group); 103 return tomoyo_path_matches_pattern(name, ptr->filename); 104} 105 106void tomoyo_put_number_union(struct tomoyo_number_union *ptr) 107{ 108 if (ptr && ptr->is_group) 109 tomoyo_put_group(ptr->group); 110} 111 112bool tomoyo_compare_number_union(const unsigned long value, 113 const struct tomoyo_number_union *ptr) 114{ 115 if (ptr->is_group) 116 return tomoyo_number_matches_group(value, value, ptr->group); 117 return value >= ptr->values[0] && value <= ptr->values[1]; 118} 119 120static void tomoyo_add_slash(struct tomoyo_path_info *buf) 121{ 122 if (buf->is_dir) 123 return; 124 /* 125 * This is OK because tomoyo_encode() reserves space for appending "/". 126 */ 127 strcat((char *) buf->name, "/"); 128 tomoyo_fill_path_info(buf); 129} 130 131/** 132 * tomoyo_strendswith - Check whether the token ends with the given token. 133 * 134 * @name: The token to check. 135 * @tail: The token to find. 136 * 137 * Returns true if @name ends with @tail, false otherwise. 138 */ 139static bool tomoyo_strendswith(const char *name, const char *tail) 140{ 141 int len; 142 143 if (!name || !tail) 144 return false; 145 len = strlen(name) - strlen(tail); 146 return len >= 0 && !strcmp(name + len, tail); 147} 148 149/** 150 * tomoyo_get_realpath - Get realpath. 151 * 152 * @buf: Pointer to "struct tomoyo_path_info". 153 * @path: Pointer to "struct path". 154 * 155 * Returns true on success, false otherwise. 156 */ 157static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) 158{ 159 buf->name = tomoyo_realpath_from_path(path); 160 if (buf->name) { 161 tomoyo_fill_path_info(buf); 162 return true; 163 } 164 return false; 165} 166 167/** 168 * tomoyo_audit_path_log - Audit path request log. 169 * 170 * @r: Pointer to "struct tomoyo_request_info". 171 * 172 * Returns 0 on success, negative value otherwise. 173 */ 174static int tomoyo_audit_path_log(struct tomoyo_request_info *r) 175{ 176 const char *operation = tomoyo_path_keyword[r->param.path.operation]; 177 const struct tomoyo_path_info *filename = r->param.path.filename; 178 if (r->granted) 179 return 0; 180 tomoyo_warn_log(r, "%s %s", operation, filename->name); 181 return tomoyo_supervisor(r, "allow_%s %s\n", operation, 182 tomoyo_file_pattern(filename)); 183} 184 185/** 186 * tomoyo_audit_path2_log - Audit path/path request log. 187 * 188 * @r: Pointer to "struct tomoyo_request_info". 189 * 190 * Returns 0 on success, negative value otherwise. 191 */ 192static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) 193{ 194 const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; 195 const struct tomoyo_path_info *filename1 = r->param.path2.filename1; 196 const struct tomoyo_path_info *filename2 = r->param.path2.filename2; 197 if (r->granted) 198 return 0; 199 tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, 200 filename2->name); 201 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 202 tomoyo_file_pattern(filename1), 203 tomoyo_file_pattern(filename2)); 204} 205 206/** 207 * tomoyo_audit_mkdev_log - Audit path/number/number/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_mkdev_log(struct tomoyo_request_info *r) 214{ 215 const char *operation = tomoyo_mkdev_keyword[r->param.mkdev.operation]; 216 const struct tomoyo_path_info *filename = r->param.mkdev.filename; 217 const unsigned int major = r->param.mkdev.major; 218 const unsigned int minor = r->param.mkdev.minor; 219 const unsigned int mode = r->param.mkdev.mode; 220 if (r->granted) 221 return 0; 222 tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, 223 major, minor); 224 return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, 225 tomoyo_file_pattern(filename), mode, major, 226 minor); 227} 228 229/** 230 * tomoyo_audit_path_number_log - Audit path/number request log. 231 * 232 * @r: Pointer to "struct tomoyo_request_info". 233 * @error: Error code. 234 * 235 * Returns 0 on success, negative value otherwise. 236 */ 237static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) 238{ 239 const u8 type = r->param.path_number.operation; 240 u8 radix; 241 const struct tomoyo_path_info *filename = r->param.path_number.filename; 242 const char *operation = tomoyo_path_number_keyword[type]; 243 char buffer[64]; 244 if (r->granted) 245 return 0; 246 switch (type) { 247 case TOMOYO_TYPE_CREATE: 248 case TOMOYO_TYPE_MKDIR: 249 case TOMOYO_TYPE_MKFIFO: 250 case TOMOYO_TYPE_MKSOCK: 251 case TOMOYO_TYPE_CHMOD: 252 radix = TOMOYO_VALUE_TYPE_OCTAL; 253 break; 254 case TOMOYO_TYPE_IOCTL: 255 radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; 256 break; 257 default: 258 radix = TOMOYO_VALUE_TYPE_DECIMAL; 259 break; 260 } 261 tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, 262 radix); 263 tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); 264 return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, 265 tomoyo_file_pattern(filename), buffer); 266} 267 268static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, 269 const struct tomoyo_acl_head *b) 270{ 271 return container_of(a, struct tomoyo_globally_readable_file_entry, 272 head)->filename == 273 container_of(b, struct tomoyo_globally_readable_file_entry, 274 head)->filename; 275} 276 277/** 278 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. 279 * 280 * @filename: Filename unconditionally permitted to open() for reading. 281 * @is_delete: True if it is a delete request. 282 * 283 * Returns 0 on success, negative value otherwise. 284 * 285 * Caller holds tomoyo_read_lock(). 286 */ 287static int tomoyo_update_globally_readable_entry(const char *filename, 288 const bool is_delete) 289{ 290 struct tomoyo_globally_readable_file_entry e = { }; 291 int error; 292 293 if (!tomoyo_correct_word(filename)) 294 return -EINVAL; 295 e.filename = tomoyo_get_name(filename); 296 if (!e.filename) 297 return -ENOMEM; 298 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 299 &tomoyo_policy_list 300 [TOMOYO_ID_GLOBALLY_READABLE], 301 tomoyo_same_globally_readable); 302 tomoyo_put_name(e.filename); 303 return error; 304} 305 306/** 307 * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. 308 * 309 * @filename: The filename to check. 310 * 311 * Returns true if any domain can open @filename for reading, false otherwise. 312 * 313 * Caller holds tomoyo_read_lock(). 314 */ 315static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * 316 filename) 317{ 318 struct tomoyo_globally_readable_file_entry *ptr; 319 bool found = false; 320 321 list_for_each_entry_rcu(ptr, &tomoyo_policy_list 322 [TOMOYO_ID_GLOBALLY_READABLE], head.list) { 323 if (!ptr->head.is_deleted && 324 tomoyo_path_matches_pattern(filename, ptr->filename)) { 325 found = true; 326 break; 327 } 328 } 329 return found; 330} 331 332/** 333 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list. 334 * 335 * @data: String to parse. 336 * @is_delete: True if it is a delete request. 337 * 338 * Returns 0 on success, negative value otherwise. 339 * 340 * Caller holds tomoyo_read_lock(). 341 */ 342int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) 343{ 344 return tomoyo_update_globally_readable_entry(data, is_delete); 345} 346 347static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, 348 const struct tomoyo_acl_head *b) 349{ 350 return container_of(a, struct tomoyo_pattern_entry, head)->pattern == 351 container_of(b, struct tomoyo_pattern_entry, head)->pattern; 352} 353 354/** 355 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. 356 * 357 * @pattern: Pathname pattern. 358 * @is_delete: True if it is a delete request. 359 * 360 * Returns 0 on success, negative value otherwise. 361 * 362 * Caller holds tomoyo_read_lock(). 363 */ 364static int tomoyo_update_file_pattern_entry(const char *pattern, 365 const bool is_delete) 366{ 367 struct tomoyo_pattern_entry e = { }; 368 int error; 369 370 if (!tomoyo_correct_word(pattern)) 371 return -EINVAL; 372 e.pattern = tomoyo_get_name(pattern); 373 if (!e.pattern) 374 return -ENOMEM; 375 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 376 &tomoyo_policy_list[TOMOYO_ID_PATTERN], 377 tomoyo_same_pattern); 378 tomoyo_put_name(e.pattern); 379 return error; 380} 381 382/** 383 * tomoyo_file_pattern - Get patterned pathname. 384 * 385 * @filename: The filename to find patterned pathname. 386 * 387 * Returns pointer to pathname pattern if matched, @filename otherwise. 388 * 389 * Caller holds tomoyo_read_lock(). 390 */ 391const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename) 392{ 393 struct tomoyo_pattern_entry *ptr; 394 const struct tomoyo_path_info *pattern = NULL; 395 396 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN], 397 head.list) { 398 if (ptr->head.is_deleted) 399 continue; 400 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 401 continue; 402 pattern = ptr->pattern; 403 if (tomoyo_strendswith(pattern->name, "/\\*")) { 404 /* Do nothing. Try to find the better match. */ 405 } else { 406 /* This would be the better match. Use this. */ 407 break; 408 } 409 } 410 if (pattern) 411 filename = pattern; 412 return filename->name; 413} 414 415/** 416 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list. 417 * 418 * @data: String to parse. 419 * @is_delete: True if it is a delete request. 420 * 421 * Returns 0 on success, negative value otherwise. 422 * 423 * Caller holds tomoyo_read_lock(). 424 */ 425int tomoyo_write_pattern_policy(char *data, const bool is_delete) 426{ 427 return tomoyo_update_file_pattern_entry(data, is_delete); 428} 429 430static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, 431 const struct tomoyo_acl_head *b) 432{ 433 return container_of(a, struct tomoyo_no_rewrite_entry, head)->pattern 434 == container_of(b, struct tomoyo_no_rewrite_entry, head) 435 ->pattern; 436} 437 438/** 439 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. 440 * 441 * @pattern: Pathname pattern that are not rewritable by default. 442 * @is_delete: True if it is a delete request. 443 * 444 * Returns 0 on success, negative value otherwise. 445 * 446 * Caller holds tomoyo_read_lock(). 447 */ 448static int tomoyo_update_no_rewrite_entry(const char *pattern, 449 const bool is_delete) 450{ 451 struct tomoyo_no_rewrite_entry e = { }; 452 int error; 453 454 if (!tomoyo_correct_word(pattern)) 455 return -EINVAL; 456 e.pattern = tomoyo_get_name(pattern); 457 if (!e.pattern) 458 return -ENOMEM; 459 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 460 &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], 461 tomoyo_same_no_rewrite); 462 tomoyo_put_name(e.pattern); 463 return error; 464} 465 466/** 467 * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. 468 * 469 * @filename: Filename to check. 470 * 471 * Returns true if @filename is specified by "deny_rewrite" directive, 472 * false otherwise. 473 * 474 * Caller holds tomoyo_read_lock(). 475 */ 476static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) 477{ 478 struct tomoyo_no_rewrite_entry *ptr; 479 bool found = false; 480 481 list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], 482 head.list) { 483 if (ptr->head.is_deleted) 484 continue; 485 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 486 continue; 487 found = true; 488 break; 489 } 490 return found; 491} 492 493/** 494 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list. 495 * 496 * @data: String to parse. 497 * @is_delete: True if it is a delete request. 498 * 499 * Returns 0 on success, negative value otherwise. 500 * 501 * Caller holds tomoyo_read_lock(). 502 */ 503int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) 504{ 505 return tomoyo_update_no_rewrite_entry(data, is_delete); 506} 507 508static bool tomoyo_check_path_acl(const struct tomoyo_request_info *r, 509 const struct tomoyo_acl_info *ptr) 510{ 511 const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), 512 head); 513 return (acl->perm & (1 << r->param.path.operation)) && 514 tomoyo_compare_name_union(r->param.path.filename, &acl->name); 515} 516 517static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r, 518 const struct tomoyo_acl_info *ptr) 519{ 520 const struct tomoyo_path_number_acl *acl = 521 container_of(ptr, typeof(*acl), head); 522 return (acl->perm & (1 << r->param.path_number.operation)) && 523 tomoyo_compare_number_union(r->param.path_number.number, 524 &acl->number) && 525 tomoyo_compare_name_union(r->param.path_number.filename, 526 &acl->name); 527} 528 529static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r, 530 const struct tomoyo_acl_info *ptr) 531{ 532 const struct tomoyo_path2_acl *acl = 533 container_of(ptr, typeof(*acl), head); 534 return (acl->perm & (1 << r->param.path2.operation)) && 535 tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) 536 && tomoyo_compare_name_union(r->param.path2.filename2, 537 &acl->name2); 538} 539 540static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r, 541 const struct tomoyo_acl_info *ptr) 542{ 543 const struct tomoyo_mkdev_acl *acl = 544 container_of(ptr, typeof(*acl), head); 545 return (acl->perm & (1 << r->param.mkdev.operation)) && 546 tomoyo_compare_number_union(r->param.mkdev.mode, 547 &acl->mode) && 548 tomoyo_compare_number_union(r->param.mkdev.major, 549 &acl->major) && 550 tomoyo_compare_number_union(r->param.mkdev.minor, 551 &acl->minor) && 552 tomoyo_compare_name_union(r->param.mkdev.filename, 553 &acl->name); 554} 555 556static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, 557 const struct tomoyo_acl_info *b) 558{ 559 const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); 560 const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); 561 return tomoyo_same_acl_head(&p1->head, &p2->head) && 562 tomoyo_same_name_union(&p1->name, &p2->name); 563} 564 565static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, 566 struct tomoyo_acl_info *b, 567 const bool is_delete) 568{ 569 u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) 570 ->perm; 571 u16 perm = *a_perm; 572 const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; 573 if (is_delete) { 574 perm &= ~b_perm; 575 if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) 576 perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); 577 else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE))) 578 perm &= ~TOMOYO_RW_MASK; 579 } else { 580 perm |= b_perm; 581 if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK) 582 perm |= (1 << TOMOYO_TYPE_READ_WRITE); 583 else if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) 584 perm |= TOMOYO_RW_MASK; 585 } 586 *a_perm = perm; 587 return !perm; 588} 589 590/** 591 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. 592 * 593 * @type: Type of operation. 594 * @filename: Filename. 595 * @domain: Pointer to "struct tomoyo_domain_info". 596 * @is_delete: True if it is a delete request. 597 * 598 * Returns 0 on success, negative value otherwise. 599 * 600 * Caller holds tomoyo_read_lock(). 601 */ 602static int tomoyo_update_path_acl(const u8 type, const char *filename, 603 struct tomoyo_domain_info * const domain, 604 const bool is_delete) 605{ 606 struct tomoyo_path_acl e = { 607 .head.type = TOMOYO_TYPE_PATH_ACL, 608 .perm = 1 << type 609 }; 610 int error; 611 if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) 612 e.perm |= TOMOYO_RW_MASK; 613 if (!tomoyo_parse_name_union(filename, &e.name)) 614 return -EINVAL; 615 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 616 tomoyo_same_path_acl, 617 tomoyo_merge_path_acl); 618 tomoyo_put_name_union(&e.name); 619 return error; 620} 621 622static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, 623 const struct tomoyo_acl_info *b) 624{ 625 const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), 626 head); 627 const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), 628 head); 629 return tomoyo_same_acl_head(&p1->head, &p2->head) 630 && tomoyo_same_name_union(&p1->name, &p2->name) 631 && tomoyo_same_number_union(&p1->mode, &p2->mode) 632 && tomoyo_same_number_union(&p1->major, &p2->major) 633 && tomoyo_same_number_union(&p1->minor, &p2->minor); 634} 635 636static bool tomoyo_merge_mkdev_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_mkdev_acl, 641 head)->perm; 642 u8 perm = *a_perm; 643 const u8 b_perm = container_of(b, struct tomoyo_mkdev_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_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. 655 * 656 * @type: Type of operation. 657 * @filename: Filename. 658 * @mode: Create mode. 659 * @major: Device major number. 660 * @minor: Device minor number. 661 * @domain: Pointer to "struct tomoyo_domain_info". 662 * @is_delete: True if it is a delete request. 663 * 664 * Returns 0 on success, negative value otherwise. 665 * 666 * Caller holds tomoyo_read_lock(). 667 */ 668static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, 669 char *mode, char *major, char *minor, 670 struct tomoyo_domain_info * const 671 domain, const bool is_delete) 672{ 673 struct tomoyo_mkdev_acl e = { 674 .head.type = TOMOYO_TYPE_MKDEV_ACL, 675 .perm = 1 << type 676 }; 677 int error = is_delete ? -ENOENT : -ENOMEM; 678 if (!tomoyo_parse_name_union(filename, &e.name) || 679 !tomoyo_parse_number_union(mode, &e.mode) || 680 !tomoyo_parse_number_union(major, &e.major) || 681 !tomoyo_parse_number_union(minor, &e.minor)) 682 goto out; 683 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 684 tomoyo_same_mkdev_acl, 685 tomoyo_merge_mkdev_acl); 686 out: 687 tomoyo_put_name_union(&e.name); 688 tomoyo_put_number_union(&e.mode); 689 tomoyo_put_number_union(&e.major); 690 tomoyo_put_number_union(&e.minor); 691 return error; 692} 693 694static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, 695 const struct tomoyo_acl_info *b) 696{ 697 const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); 698 const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); 699 return tomoyo_same_acl_head(&p1->head, &p2->head) 700 && tomoyo_same_name_union(&p1->name1, &p2->name1) 701 && tomoyo_same_name_union(&p1->name2, &p2->name2); 702} 703 704static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, 705 struct tomoyo_acl_info *b, 706 const bool is_delete) 707{ 708 u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) 709 ->perm; 710 u8 perm = *a_perm; 711 const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; 712 if (is_delete) 713 perm &= ~b_perm; 714 else 715 perm |= b_perm; 716 *a_perm = perm; 717 return !perm; 718} 719 720/** 721 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. 722 * 723 * @type: Type of operation. 724 * @filename1: First filename. 725 * @filename2: Second filename. 726 * @domain: Pointer to "struct tomoyo_domain_info". 727 * @is_delete: True if it is a delete request. 728 * 729 * Returns 0 on success, negative value otherwise. 730 * 731 * Caller holds tomoyo_read_lock(). 732 */ 733static int tomoyo_update_path2_acl(const u8 type, const char *filename1, 734 const char *filename2, 735 struct tomoyo_domain_info * const domain, 736 const bool is_delete) 737{ 738 struct tomoyo_path2_acl e = { 739 .head.type = TOMOYO_TYPE_PATH2_ACL, 740 .perm = 1 << type 741 }; 742 int error = is_delete ? -ENOENT : -ENOMEM; 743 if (!tomoyo_parse_name_union(filename1, &e.name1) || 744 !tomoyo_parse_name_union(filename2, &e.name2)) 745 goto out; 746 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 747 tomoyo_same_path2_acl, 748 tomoyo_merge_path2_acl); 749 out: 750 tomoyo_put_name_union(&e.name1); 751 tomoyo_put_name_union(&e.name2); 752 return error; 753} 754 755/** 756 * tomoyo_path_permission - Check permission for single path operation. 757 * 758 * @r: Pointer to "struct tomoyo_request_info". 759 * @operation: Type of operation. 760 * @filename: Filename to check. 761 * 762 * Returns 0 on success, negative value otherwise. 763 * 764 * Caller holds tomoyo_read_lock(). 765 */ 766int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, 767 const struct tomoyo_path_info *filename) 768{ 769 int error; 770 771 next: 772 r->type = tomoyo_p2mac[operation]; 773 r->mode = tomoyo_get_mode(r->profile, r->type); 774 if (r->mode == TOMOYO_CONFIG_DISABLED) 775 return 0; 776 r->param_type = TOMOYO_TYPE_PATH_ACL; 777 r->param.path.filename = filename; 778 r->param.path.operation = operation; 779 do { 780 tomoyo_check_acl(r, tomoyo_check_path_acl); 781 if (!r->granted && operation == TOMOYO_TYPE_READ && 782 !r->domain->ignore_global_allow_read && 783 tomoyo_globally_readable_file(filename)) 784 r->granted = true; 785 error = tomoyo_audit_path_log(r); 786 /* 787 * Do not retry for execute request, for alias may have 788 * changed. 789 */ 790 } while (error == TOMOYO_RETRY_REQUEST && 791 operation != TOMOYO_TYPE_EXECUTE); 792 /* 793 * Since "allow_truncate" doesn't imply "allow_rewrite" permission, 794 * we need to check "allow_rewrite" permission if the filename is 795 * specified by "deny_rewrite" keyword. 796 */ 797 if (!error && operation == TOMOYO_TYPE_TRUNCATE && 798 tomoyo_no_rewrite_file(filename)) { 799 operation = TOMOYO_TYPE_REWRITE; 800 goto next; 801 } 802 return error; 803} 804 805static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, 806 const struct tomoyo_acl_info *b) 807{ 808 const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), 809 head); 810 const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), 811 head); 812 return tomoyo_same_acl_head(&p1->head, &p2->head) 813 && tomoyo_same_name_union(&p1->name, &p2->name) 814 && tomoyo_same_number_union(&p1->number, &p2->number); 815} 816 817static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, 818 struct tomoyo_acl_info *b, 819 const bool is_delete) 820{ 821 u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, 822 head)->perm; 823 u8 perm = *a_perm; 824 const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) 825 ->perm; 826 if (is_delete) 827 perm &= ~b_perm; 828 else 829 perm |= b_perm; 830 *a_perm = perm; 831 return !perm; 832} 833 834/** 835 * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. 836 * 837 * @type: Type of operation. 838 * @filename: Filename. 839 * @number: Number. 840 * @domain: Pointer to "struct tomoyo_domain_info". 841 * @is_delete: True if it is a delete request. 842 * 843 * Returns 0 on success, negative value otherwise. 844 */ 845static int tomoyo_update_path_number_acl(const u8 type, const char *filename, 846 char *number, 847 struct tomoyo_domain_info * const 848 domain, 849 const bool is_delete) 850{ 851 struct tomoyo_path_number_acl e = { 852 .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, 853 .perm = 1 << type 854 }; 855 int error = is_delete ? -ENOENT : -ENOMEM; 856 if (!tomoyo_parse_name_union(filename, &e.name)) 857 return -EINVAL; 858 if (!tomoyo_parse_number_union(number, &e.number)) 859 goto out; 860 error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, 861 tomoyo_same_path_number_acl, 862 tomoyo_merge_path_number_acl); 863 out: 864 tomoyo_put_name_union(&e.name); 865 tomoyo_put_number_union(&e.number); 866 return error; 867} 868 869/** 870 * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". 871 * 872 * @type: Type of operation. 873 * @path: Pointer to "struct path". 874 * @number: Number. 875 * 876 * Returns 0 on success, negative value otherwise. 877 */ 878int tomoyo_path_number_perm(const u8 type, struct path *path, 879 unsigned long number) 880{ 881 struct tomoyo_request_info r; 882 int error = -ENOMEM; 883 struct tomoyo_path_info buf; 884 int idx; 885 886 if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) 887 == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) 888 return 0; 889 idx = tomoyo_read_lock(); 890 if (!tomoyo_get_realpath(&buf, path)) 891 goto out; 892 if (type == TOMOYO_TYPE_MKDIR) 893 tomoyo_add_slash(&buf); 894 r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; 895 r.param.path_number.operation = type; 896 r.param.path_number.filename = &buf; 897 r.param.path_number.number = number; 898 do { 899 tomoyo_check_acl(&r, tomoyo_check_path_number_acl); 900 error = tomoyo_audit_path_number_log(&r); 901 } while (error == TOMOYO_RETRY_REQUEST); 902 kfree(buf.name); 903 out: 904 tomoyo_read_unlock(idx); 905 if (r.mode != TOMOYO_CONFIG_ENFORCING) 906 error = 0; 907 return error; 908} 909 910/** 911 * tomoyo_check_open_permission - Check permission for "read" and "write". 912 * 913 * @domain: Pointer to "struct tomoyo_domain_info". 914 * @path: Pointer to "struct path". 915 * @flag: Flags for open(). 916 * 917 * Returns 0 on success, negative value otherwise. 918 */ 919int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, 920 struct path *path, const int flag) 921{ 922 const u8 acc_mode = ACC_MODE(flag); 923 int error = -ENOMEM; 924 struct tomoyo_path_info buf; 925 struct tomoyo_request_info r; 926 int idx; 927 928 if (!path->mnt || 929 (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) 930 return 0; 931 buf.name = NULL; 932 r.mode = TOMOYO_CONFIG_DISABLED; 933 idx = tomoyo_read_lock(); 934 if (!tomoyo_get_realpath(&buf, path)) 935 goto out; 936 error = 0; 937 /* 938 * If the filename is specified by "deny_rewrite" keyword, 939 * we need to check "allow_rewrite" permission when the filename is not 940 * opened for append mode or the filename is truncated at open time. 941 */ 942 if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) 943 && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) 944 != TOMOYO_CONFIG_DISABLED) { 945 if (!tomoyo_get_realpath(&buf, path)) { 946 error = -ENOMEM; 947 goto out; 948 } 949 if (tomoyo_no_rewrite_file(&buf)) 950 error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, 951 &buf); 952 } 953 if (!error && acc_mode && 954 tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) 955 != TOMOYO_CONFIG_DISABLED) { 956 u8 operation; 957 if (!buf.name && !tomoyo_get_realpath(&buf, path)) { 958 error = -ENOMEM; 959 goto out; 960 } 961 if (acc_mode == (MAY_READ | MAY_WRITE)) 962 operation = TOMOYO_TYPE_READ_WRITE; 963 else if (acc_mode == MAY_READ) 964 operation = TOMOYO_TYPE_READ; 965 else 966 operation = TOMOYO_TYPE_WRITE; 967 error = tomoyo_path_permission(&r, operation, &buf); 968 } 969 out: 970 kfree(buf.name); 971 tomoyo_read_unlock(idx); 972 if (r.mode != TOMOYO_CONFIG_ENFORCING) 973 error = 0; 974 return error; 975} 976 977/** 978 * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount". 979 * 980 * @operation: Type of operation. 981 * @path: Pointer to "struct path". 982 * 983 * Returns 0 on success, negative value otherwise. 984 */ 985int tomoyo_path_perm(const u8 operation, struct path *path) 986{ 987 int error = -ENOMEM; 988 struct tomoyo_path_info buf; 989 struct tomoyo_request_info r; 990 int idx; 991 992 if (!path->mnt) 993 return 0; 994 if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) 995 == TOMOYO_CONFIG_DISABLED) 996 return 0; 997 buf.name = NULL; 998 idx = tomoyo_read_lock(); 999 if (!tomoyo_get_realpath(&buf, path)) 1000 goto out; 1001 switch (operation) { 1002 case TOMOYO_TYPE_REWRITE: 1003 if (!tomoyo_no_rewrite_file(&buf)) { 1004 error = 0; 1005 goto out; 1006 } 1007 break; 1008 case TOMOYO_TYPE_RMDIR: 1009 case TOMOYO_TYPE_CHROOT: 1010 case TOMOYO_TYPE_UMOUNT: 1011 tomoyo_add_slash(&buf); 1012 break; 1013 } 1014 error = tomoyo_path_permission(&r, operation, &buf); 1015 out: 1016 kfree(buf.name); 1017 tomoyo_read_unlock(idx); 1018 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1019 error = 0; 1020 return error; 1021} 1022 1023/** 1024 * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". 1025 * 1026 * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) 1027 * @path: Pointer to "struct path". 1028 * @mode: Create mode. 1029 * @dev: Device number. 1030 * 1031 * Returns 0 on success, negative value otherwise. 1032 */ 1033int tomoyo_mkdev_perm(const u8 operation, struct path *path, 1034 const unsigned int mode, unsigned int dev) 1035{ 1036 struct tomoyo_request_info r; 1037 int error = -ENOMEM; 1038 struct tomoyo_path_info buf; 1039 int idx; 1040 1041 if (!path->mnt || 1042 tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) 1043 == TOMOYO_CONFIG_DISABLED) 1044 return 0; 1045 idx = tomoyo_read_lock(); 1046 error = -ENOMEM; 1047 if (tomoyo_get_realpath(&buf, path)) { 1048 dev = new_decode_dev(dev); 1049 r.param_type = TOMOYO_TYPE_MKDEV_ACL; 1050 r.param.mkdev.filename = &buf; 1051 r.param.mkdev.operation = operation; 1052 r.param.mkdev.mode = mode; 1053 r.param.mkdev.major = MAJOR(dev); 1054 r.param.mkdev.minor = MINOR(dev); 1055 tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); 1056 error = tomoyo_audit_mkdev_log(&r); 1057 kfree(buf.name); 1058 } 1059 tomoyo_read_unlock(idx); 1060 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1061 error = 0; 1062 return error; 1063} 1064 1065/** 1066 * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". 1067 * 1068 * @operation: Type of operation. 1069 * @path1: Pointer to "struct path". 1070 * @path2: Pointer to "struct path". 1071 * 1072 * Returns 0 on success, negative value otherwise. 1073 */ 1074int tomoyo_path2_perm(const u8 operation, struct path *path1, 1075 struct path *path2) 1076{ 1077 int error = -ENOMEM; 1078 struct tomoyo_path_info buf1; 1079 struct tomoyo_path_info buf2; 1080 struct tomoyo_request_info r; 1081 int idx; 1082 1083 if (!path1->mnt || !path2->mnt || 1084 tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) 1085 == TOMOYO_CONFIG_DISABLED) 1086 return 0; 1087 buf1.name = NULL; 1088 buf2.name = NULL; 1089 idx = tomoyo_read_lock(); 1090 if (!tomoyo_get_realpath(&buf1, path1) || 1091 !tomoyo_get_realpath(&buf2, path2)) 1092 goto out; 1093 switch (operation) { 1094 struct dentry *dentry; 1095 case TOMOYO_TYPE_RENAME: 1096 case TOMOYO_TYPE_LINK: 1097 dentry = path1->dentry; 1098 if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) 1099 break; 1100 /* fall through */ 1101 case TOMOYO_TYPE_PIVOT_ROOT: 1102 tomoyo_add_slash(&buf1); 1103 tomoyo_add_slash(&buf2); 1104 break; 1105 } 1106 r.param_type = TOMOYO_TYPE_PATH2_ACL; 1107 r.param.path2.operation = operation; 1108 r.param.path2.filename1 = &buf1; 1109 r.param.path2.filename2 = &buf2; 1110 do { 1111 tomoyo_check_acl(&r, tomoyo_check_path2_acl); 1112 error = tomoyo_audit_path2_log(&r); 1113 } while (error == TOMOYO_RETRY_REQUEST); 1114 out: 1115 kfree(buf1.name); 1116 kfree(buf2.name); 1117 tomoyo_read_unlock(idx); 1118 if (r.mode != TOMOYO_CONFIG_ENFORCING) 1119 error = 0; 1120 return error; 1121} 1122 1123/** 1124 * tomoyo_write_file_policy - Update file related list. 1125 * 1126 * @data: String to parse. 1127 * @domain: Pointer to "struct tomoyo_domain_info". 1128 * @is_delete: True if it is a delete request. 1129 * 1130 * Returns 0 on success, negative value otherwise. 1131 * 1132 * Caller holds tomoyo_read_lock(). 1133 */ 1134int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 1135 const bool is_delete) 1136{ 1137 char *w[5]; 1138 u8 type; 1139 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) 1140 return -EINVAL; 1141 if (strncmp(w[0], "allow_", 6)) 1142 goto out; 1143 w[0] += 6; 1144 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { 1145 if (strcmp(w[0], tomoyo_path_keyword[type])) 1146 continue; 1147 return tomoyo_update_path_acl(type, w[1], domain, is_delete); 1148 } 1149 if (!w[2][0]) 1150 goto out; 1151 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { 1152 if (strcmp(w[0], tomoyo_path2_keyword[type])) 1153 continue; 1154 return tomoyo_update_path2_acl(type, w[1], w[2], domain, 1155 is_delete); 1156 } 1157 for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { 1158 if (strcmp(w[0], tomoyo_path_number_keyword[type])) 1159 continue; 1160 return tomoyo_update_path_number_acl(type, w[1], w[2], domain, 1161 is_delete); 1162 } 1163 if (!w[3][0] || !w[4][0]) 1164 goto out; 1165 for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) { 1166 if (strcmp(w[0], tomoyo_mkdev_keyword[type])) 1167 continue; 1168 return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3], 1169 w[4], domain, is_delete); 1170 } 1171 out: 1172 return -EINVAL; 1173} 1174