Commit a8157d6
fix: write through the handle rather than reopening the name
write_private/2 opened the file exclusively, closed the handle, and then
reopened the same name with File.write/2 to put the content in. The
exclusive open is what establishes that the name did not exist, and
closing it to reopen by path gives that proof back: anything able to
create the name in between is handed the configuration, which is the
disclosure the exclusive open was added to prevent.
So the bytes now go through the handle the open returned, and the name
is never reopened to place content. The content can only reach the inode
this call created, whatever becomes of the name afterwards. Creation and
filling are one movement for the same reason - there is no longer a way
here to bring one of these files into existence without also placing its
content, because separating the two is what let the reopen back in, so
create_private/1 is gone and write_private/2 is what call sites use.
chmod is now the only step that goes by path, and it has to: OTP has
nothing that sets a mode on an open file. :file.change_mode/2 rejects a
handle with badarg and :file.write_file_info/2 with function_clause, and
those, with raw_write_file_info/2, are the whole of what :file offers.
The asymmetry is accepted rather than overlooked. By the time the chmod
runs the content is already committed to this call's inode, so a name
swapped underneath it does not receive the configuration - it gets
narrowed, which is Castle setting some other file to 0600 inside a
directory it verified empty and made 0700. A nuisance, not a disclosure.
The test asserts both halves of that, so the cost is pinned rather than
merely asserted in a comment.
The mode still goes on after the content rather than before, and the
reason is now stated properly: it is about the writes that come later.
The scratch is written twice more after Castle creates it - the peer's
pipeline writes the resolved configuration over it, then this module
writes it again - and both reopen the name, so a 0440 model applied any
earlier would leave a file that cannot be reopened for writing.
One of those two is Config.Provider.write_config!, which is File.write/2
in Elixir's own code, running in the peer's VM. Driving Elixir's
pipeline is what this module exists for, so that is not ours to change
and is not worked around. Holding the creation handle open across the
peer's run would not cover it either, and the comment says why it must
not be tried: the peer writes by name in a VM of its own, and a handle
kept here would point at whichever inode the name had when it was
opened. Elixir truncates the same inode today; one that wrote a
temporary file and renamed it would leave the handle on an orphan and
the configuration written through it would silently be nobody's. Those
two writes rest on the directory - verified empty, 0700, holding only
names this call created - and that is what the directory is for.
The test stands between the exclusive open and the write, which is why
create_exclusive/1 and fill/3 are public: the name is swapped for a
symlink to a decoy in between, and the configuration is found in neither
the decoy nor anywhere the name leads. With the name left alone the two
behaviours are identical, so there is no other way to tell content that
went to the inode from content that went to the name. It fails against
ad68d0e because the handle it writes through does not exist there -
write_private/2 had no seam to stand in, which is the same shape of
discrimination as secure_dir/1 last time and worth saying plainly rather
than dressing up.
Refs: #13
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C4oaMvbR1cbxrZBj8qwkqN1 parent ad68d0e commit a8157d6
3 files changed
Lines changed: 201 additions & 97 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
97 | 97 | | |
98 | 98 | | |
99 | 99 | | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
108 | 127 | | |
109 | 128 | | |
110 | 129 | | |
| |||
145 | 164 | | |
146 | 165 | | |
147 | 166 | | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
169 | | - | |
170 | | - | |
171 | | - | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
172 | 195 | | |
173 | 196 | | |
174 | 197 | | |
| |||
380 | 403 | | |
381 | 404 | | |
382 | 405 | | |
383 | | - | |
384 | | - | |
385 | | - | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
390 | 423 | | |
391 | 424 | | |
392 | 425 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
658 | 658 | | |
659 | 659 | | |
660 | 660 | | |
661 | | - | |
662 | | - | |
663 | | - | |
664 | | - | |
665 | | - | |
666 | | - | |
667 | | - | |
668 | | - | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
669 | 669 | | |
670 | | - | |
671 | | - | |
672 | | - | |
673 | | - | |
674 | | - | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
679 | | - | |
680 | | - | |
681 | | - | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
682 | 699 | | |
683 | 700 | | |
684 | 701 | | |
| |||
688 | 705 | | |
689 | 706 | | |
690 | 707 | | |
691 | | - | |
692 | | - | |
693 | | - | |
694 | | - | |
695 | | - | |
696 | | - | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
| 716 | + | |
| 717 | + | |
697 | 718 | | |
698 | 719 | | |
699 | 720 | | |
| |||
758 | 779 | | |
759 | 780 | | |
760 | 781 | | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
761 | 785 | | |
762 | 786 | | |
763 | 787 | | |
764 | 788 | | |
765 | | - | |
766 | | - | |
| 789 | + | |
| 790 | + | |
767 | 791 | | |
768 | 792 | | |
769 | 793 | | |
770 | 794 | | |
771 | 795 | | |
772 | 796 | | |
773 | 797 | | |
774 | | - | |
775 | | - | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
776 | 801 | | |
777 | | - | |
778 | | - | |
779 | | - | |
780 | | - | |
781 | | - | |
782 | | - | |
| 802 | + | |
| 803 | + | |
783 | 804 | | |
784 | | - | |
| 805 | + | |
785 | 806 | | |
786 | 807 | | |
787 | 808 | | |
788 | 809 | | |
789 | | - | |
790 | | - | |
791 | | - | |
792 | | - | |
793 | | - | |
794 | | - | |
| 810 | + | |
| 811 | + | |
| 812 | + | |
| 813 | + | |
| 814 | + | |
| 815 | + | |
| 816 | + | |
| 817 | + | |
| 818 | + | |
| 819 | + | |
| 820 | + | |
| 821 | + | |
| 822 | + | |
| 823 | + | |
| 824 | + | |
| 825 | + | |
| 826 | + | |
| 827 | + | |
| 828 | + | |
| 829 | + | |
| 830 | + | |
| 831 | + | |
795 | 832 | | |
796 | 833 | | |
797 | | - | |
| 834 | + | |
798 | 835 | | |
799 | 836 | | |
800 | 837 | | |
| |||
0 commit comments