1 |
On 01/17/2018 12:14 PM, William Hubbs wrote: |
2 |
>> |
3 |
>> 1. I could create /run/foo with owner "foo", and then create |
4 |
>> /run/foo/bar with owner "foo". That can be done without modifying |
5 |
>> existing permissions, but it's not safe, because you wind up working |
6 |
>> as root in the directory /run/foo which is owned by the non-root |
7 |
>> "foo" user. If newpath disallows that unsafe operation, this approach |
8 |
>> is out. |
9 |
>> |
10 |
>> ... |
11 |
>> |
12 |
>> 3. I can create /run/foo with owner "foo", and then setuid to the foo |
13 |
>> user. Now, *as the foo user* I can create /run/foo/bar, which will be |
14 |
>> owned by "foo". There's no risk in doing so, because the "foo" user |
15 |
>> can only trick himself. Moreover, the directory is writable only by |
16 |
>> root and the OpenRC user (currently: foo) at that point, so the extra |
17 |
>> safety precautions don't get in the way. |
18 |
> |
19 |
> |
20 |
> In both approaches 1 and 3, the first step will be to create the |
21 |
> directory /run/foo then optionally adjust permissions on it. At that |
22 |
> point newpath will exit. |
23 |
> |
24 |
> When the second invocation of newpath starts, we know /run/foo/bar |
25 |
> does not exist, and creating /run/foo/bar will fail if /run/foo doesn't |
26 |
> exist. |
27 |
> |
28 |
> Since that's true, I don't see what the difference is |
29 |
> between approaches 1 and 3 or what makes approach 1 so unsafe. Call me |
30 |
> dense if you must, lol, I'm just not getting it. At this point we know |
31 |
> that /run/foo is owned by foo, and I've never heard that root working in |
32 |
> a directory it doesn't own isn't safe. |
33 |
|
34 |
Not at all. I'm working this out as I go, so better to speak up if |
35 |
something looks fishy. |
36 |
|
37 |
There are a few risks that I see with the first approach... |
38 |
|
39 |
|
40 |
Risk #1: From what I can tell, the current implementation of checkpath |
41 |
first creates the path, and then adjusts the ownership and permissions |
42 |
on it. After /run/foo/bar has been created but before the permissions |
43 |
and ownership are changed, the "foo" user can replace "bar" with a hard |
44 |
link (because he owns /run/foo). The lchown/chmod will operate on the |
45 |
target of that link, and if he's fast enough, then the "foo" user can |
46 |
use that to take over root's files. (Limited to /run in this example, |
47 |
but that's beside the point.) |
48 |
|
49 |
Maybe that can be avoided. Is there a portable way to atomically create |
50 |
a file/directory with its ownership and permissions already set? Or is |
51 |
it possible to operate on the descriptor that you get back when creating |
52 |
the path? |
53 |
|
54 |
|
55 |
Risk #2: Instead consider a four-component path /run/foo/bar/baz. If you |
56 |
start creating those directories with owner "foo", then when you get to |
57 |
creating "baz", it's possible that "bar" has been replaced by a symlink |
58 |
somewhere else. |
59 |
|
60 |
Certain tricks exist to avoid that, but I'm not an expert on them and I |
61 |
don't know how portable or secure they really are. For example, you |
62 |
might get the descriptor of "bar" and then use openat(dirfd,...) instead |
63 |
of open(...) to create "baz". |
64 |
|
65 |
|
66 |
If both of those can be solved portably, then all you have to worry |
67 |
about is everything I haven't thought of =) |