| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * AppArmor security module |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Copyright (C) 1998-2008 Novell/SUSE |
|---|
| 7 | 8 | * Copyright 2009-2017 Canonical Ltd. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or |
|---|
| 10 | | - * modify it under the terms of the GNU General Public License as |
|---|
| 11 | | - * published by the Free Software Foundation, version 2 of the |
|---|
| 12 | | - * License. |
|---|
| 13 | 9 | */ |
|---|
| 14 | 10 | |
|---|
| 15 | 11 | #include <linux/fs.h> |
|---|
| 16 | 12 | #include <linux/mount.h> |
|---|
| 17 | 13 | #include <linux/namei.h> |
|---|
| 14 | +#include <uapi/linux/mount.h> |
|---|
| 18 | 15 | |
|---|
| 19 | 16 | #include "include/apparmor.h" |
|---|
| 20 | 17 | #include "include/audit.h" |
|---|
| .. | .. |
|---|
| 232 | 229 | "failed srcname match", |
|---|
| 233 | 230 | "failed type match", |
|---|
| 234 | 231 | "failed flags match", |
|---|
| 235 | | - "failed data match" |
|---|
| 232 | + "failed data match", |
|---|
| 233 | + "failed perms check" |
|---|
| 236 | 234 | }; |
|---|
| 237 | 235 | |
|---|
| 238 | 236 | /* |
|---|
| .. | .. |
|---|
| 287 | 285 | return 0; |
|---|
| 288 | 286 | } |
|---|
| 289 | 287 | |
|---|
| 290 | | - /* failed at end of flags match */ |
|---|
| 291 | | - return 4; |
|---|
| 288 | + /* failed at perms check, don't confuse with flags match */ |
|---|
| 289 | + return 6; |
|---|
| 292 | 290 | } |
|---|
| 293 | 291 | |
|---|
| 294 | 292 | |
|---|
| .. | .. |
|---|
| 411 | 409 | |
|---|
| 412 | 410 | binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA; |
|---|
| 413 | 411 | |
|---|
| 414 | | - get_buffers(buffer); |
|---|
| 412 | + buffer = aa_get_buffer(false); |
|---|
| 413 | + if (!buffer) |
|---|
| 414 | + return -ENOMEM; |
|---|
| 415 | 415 | error = fn_for_each_confined(label, profile, |
|---|
| 416 | 416 | match_mnt(profile, path, buffer, NULL, NULL, NULL, |
|---|
| 417 | 417 | flags, data, binary)); |
|---|
| 418 | | - put_buffers(buffer); |
|---|
| 418 | + aa_put_buffer(buffer); |
|---|
| 419 | 419 | |
|---|
| 420 | 420 | return error; |
|---|
| 421 | 421 | } |
|---|
| .. | .. |
|---|
| 440 | 440 | if (error) |
|---|
| 441 | 441 | return error; |
|---|
| 442 | 442 | |
|---|
| 443 | | - get_buffers(buffer, old_buffer); |
|---|
| 443 | + buffer = aa_get_buffer(false); |
|---|
| 444 | + old_buffer = aa_get_buffer(false); |
|---|
| 445 | + error = -ENOMEM; |
|---|
| 446 | + if (!buffer || !old_buffer) |
|---|
| 447 | + goto out; |
|---|
| 448 | + |
|---|
| 444 | 449 | error = fn_for_each_confined(label, profile, |
|---|
| 445 | 450 | match_mnt(profile, path, buffer, &old_path, old_buffer, |
|---|
| 446 | 451 | NULL, flags, NULL, false)); |
|---|
| 447 | | - put_buffers(buffer, old_buffer); |
|---|
| 452 | +out: |
|---|
| 453 | + aa_put_buffer(buffer); |
|---|
| 454 | + aa_put_buffer(old_buffer); |
|---|
| 448 | 455 | path_put(&old_path); |
|---|
| 449 | 456 | |
|---|
| 450 | 457 | return error; |
|---|
| .. | .. |
|---|
| 464 | 471 | flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE | |
|---|
| 465 | 472 | MS_UNBINDABLE); |
|---|
| 466 | 473 | |
|---|
| 467 | | - get_buffers(buffer); |
|---|
| 474 | + buffer = aa_get_buffer(false); |
|---|
| 475 | + if (!buffer) |
|---|
| 476 | + return -ENOMEM; |
|---|
| 468 | 477 | error = fn_for_each_confined(label, profile, |
|---|
| 469 | 478 | match_mnt(profile, path, buffer, NULL, NULL, NULL, |
|---|
| 470 | 479 | flags, NULL, false)); |
|---|
| 471 | | - put_buffers(buffer); |
|---|
| 480 | + aa_put_buffer(buffer); |
|---|
| 472 | 481 | |
|---|
| 473 | 482 | return error; |
|---|
| 474 | 483 | } |
|---|
| .. | .. |
|---|
| 491 | 500 | if (error) |
|---|
| 492 | 501 | return error; |
|---|
| 493 | 502 | |
|---|
| 494 | | - get_buffers(buffer, old_buffer); |
|---|
| 503 | + buffer = aa_get_buffer(false); |
|---|
| 504 | + old_buffer = aa_get_buffer(false); |
|---|
| 505 | + error = -ENOMEM; |
|---|
| 506 | + if (!buffer || !old_buffer) |
|---|
| 507 | + goto out; |
|---|
| 495 | 508 | error = fn_for_each_confined(label, profile, |
|---|
| 496 | 509 | match_mnt(profile, path, buffer, &old_path, old_buffer, |
|---|
| 497 | 510 | NULL, MS_MOVE, NULL, false)); |
|---|
| 498 | | - put_buffers(buffer, old_buffer); |
|---|
| 511 | +out: |
|---|
| 512 | + aa_put_buffer(buffer); |
|---|
| 513 | + aa_put_buffer(old_buffer); |
|---|
| 499 | 514 | path_put(&old_path); |
|---|
| 500 | 515 | |
|---|
| 501 | 516 | return error; |
|---|
| .. | .. |
|---|
| 536 | 551 | } |
|---|
| 537 | 552 | } |
|---|
| 538 | 553 | |
|---|
| 539 | | - get_buffers(buffer, dev_buffer); |
|---|
| 554 | + buffer = aa_get_buffer(false); |
|---|
| 555 | + if (!buffer) { |
|---|
| 556 | + error = -ENOMEM; |
|---|
| 557 | + goto out; |
|---|
| 558 | + } |
|---|
| 540 | 559 | if (dev_path) { |
|---|
| 560 | + dev_buffer = aa_get_buffer(false); |
|---|
| 561 | + if (!dev_buffer) { |
|---|
| 562 | + error = -ENOMEM; |
|---|
| 563 | + goto out; |
|---|
| 564 | + } |
|---|
| 541 | 565 | error = fn_for_each_confined(label, profile, |
|---|
| 542 | 566 | match_mnt(profile, path, buffer, dev_path, dev_buffer, |
|---|
| 543 | 567 | type, flags, data, binary)); |
|---|
| .. | .. |
|---|
| 546 | 570 | match_mnt_path_str(profile, path, buffer, dev_name, |
|---|
| 547 | 571 | type, flags, data, binary, NULL)); |
|---|
| 548 | 572 | } |
|---|
| 549 | | - put_buffers(buffer, dev_buffer); |
|---|
| 573 | + |
|---|
| 574 | +out: |
|---|
| 575 | + aa_put_buffer(buffer); |
|---|
| 576 | + aa_put_buffer(dev_buffer); |
|---|
| 550 | 577 | if (dev_path) |
|---|
| 551 | 578 | path_put(dev_path); |
|---|
| 552 | 579 | |
|---|
| .. | .. |
|---|
| 594 | 621 | AA_BUG(!label); |
|---|
| 595 | 622 | AA_BUG(!mnt); |
|---|
| 596 | 623 | |
|---|
| 597 | | - get_buffers(buffer); |
|---|
| 624 | + buffer = aa_get_buffer(false); |
|---|
| 625 | + if (!buffer) |
|---|
| 626 | + return -ENOMEM; |
|---|
| 627 | + |
|---|
| 598 | 628 | error = fn_for_each_confined(label, profile, |
|---|
| 599 | 629 | profile_umount(profile, &path, buffer)); |
|---|
| 600 | | - put_buffers(buffer); |
|---|
| 630 | + aa_put_buffer(buffer); |
|---|
| 601 | 631 | |
|---|
| 602 | 632 | return error; |
|---|
| 603 | 633 | } |
|---|
| .. | .. |
|---|
| 670 | 700 | AA_BUG(!old_path); |
|---|
| 671 | 701 | AA_BUG(!new_path); |
|---|
| 672 | 702 | |
|---|
| 673 | | - get_buffers(old_buffer, new_buffer); |
|---|
| 674 | | - target = fn_label_build(label, profile, GFP_ATOMIC, |
|---|
| 703 | + old_buffer = aa_get_buffer(false); |
|---|
| 704 | + new_buffer = aa_get_buffer(false); |
|---|
| 705 | + error = -ENOMEM; |
|---|
| 706 | + if (!old_buffer || !new_buffer) |
|---|
| 707 | + goto out; |
|---|
| 708 | + target = fn_label_build(label, profile, GFP_KERNEL, |
|---|
| 675 | 709 | build_pivotroot(profile, new_path, new_buffer, |
|---|
| 676 | 710 | old_path, old_buffer)); |
|---|
| 677 | 711 | if (!target) { |
|---|
| .. | .. |
|---|
| 685 | 719 | aa_put_label(target); |
|---|
| 686 | 720 | goto out; |
|---|
| 687 | 721 | } |
|---|
| 722 | + aa_put_label(target); |
|---|
| 688 | 723 | } else |
|---|
| 689 | 724 | /* already audited error */ |
|---|
| 690 | 725 | error = PTR_ERR(target); |
|---|
| 691 | 726 | out: |
|---|
| 692 | | - put_buffers(old_buffer, new_buffer); |
|---|
| 727 | + aa_put_buffer(old_buffer); |
|---|
| 728 | + aa_put_buffer(new_buffer); |
|---|
| 693 | 729 | |
|---|
| 694 | 730 | return error; |
|---|
| 695 | 731 | |
|---|