[RFC PATCH 5/9] Define user structure for events and responses.

Tingmao Wang m at maowtm.org
Wed Mar 26 00:02:38 UTC 2025


On 3/12/25 11:49, Mickaël Salaün wrote:
> On Tue, Mar 11, 2025 at 11:18:49PM +0000, Tingmao Wang wrote:
>> On 3/11/25 19:28, Mickaël Salaün wrote:
>>> On Mon, Mar 10, 2025 at 12:39:04AM +0000, Tingmao Wang wrote:
>>>> On 3/6/25 03:05, Tingmao Wang wrote:
>>>> [...]
>>>>> This is also motivated by the potential UX I'm thinking of. For example,
>>>>> if a newly installed application tries to create ~/.app-name, it will be
>>>>> much more reassuring and convenient to the user if we can show something
>>>>> like
>>>>>
>>>>>        [program] wants to mkdir ~/.app-name. Allow this and future
>>>>>        access to the new directory?
>>>>>
>>>>> rather than just "[program] wants to mkdir under ~". (The "Allow this
>>>>> and future access to the new directory" bit is made possible by the
>>>>> supervisor knowing the name of the file/directory being created, and can
>>>>> remember them / write them out to a persistent profile etc)
>>>>
>>>> Another significant motivation, which I forgot to mention, is to auto-grant
>>>> access to newly created files/sockets etc under things like /tmp,
>>>> $XDG_RUNTIME_DIR, or ~/Downloads.
>>>
>>> What do you mean?  What is not currently possible?
>>
>> It is not currently possible with landlock to say "I will allow this
>> application access to create and open new file/folders under this directory,
>> change or delete the files it creates, but not touch any existing files".
>> Landlock supervisor can make this possible (keeping track via its own state
>> to allow future requests on the new file, or modifying the domain if we
>> support that), but for that the supervisor has to know what file the
>> application tried to create, hence motivating sending filename.
> 
> This capability would be at least inconsistent, and dangerous at worse,
> because of policy inconsistencies over time.  A sandbox policy should be
> seen over several invocations of the same sandbox.  See related deny
> listing issues: https://github.com/landlock-lsm/linux/issues/28
> 
> Let's say a first instance of the sandbox can create files and access
> them, but not other existing files in the same directory.  A second
> instance of this sandbox would not be able to access the files the same
> application created, so it will not be able to clean them if required.
> That could be OK in the case of the ~/Downloads directory but I think it
> would be weird for users to not be able to open their previous
> downloaded files from the browser, whereas it was allowed before.
> 
> For such use case, if we want to avoid new browser instances to access
> old downloaded files, I'd recommand to create a new download directory
> per browser/sandbox launch.
> 

I had some more thoughts on this - In terms of inconsistency / security 
implications of such a supervisor behaviour, I think I can identify two 
aspects:

First is policy inconsistency over different instances / restarts (like 
the example you mentioned about not being able to open previously 
downloaded files).  I think in this case, this is fine and would not be 
dangerous, because it will only result in extra permission requests 
(potentially the user having to allow the access again, or maybe the 
sandboxer can remember it from last time and auto-allow it internally). 
(whereas an inconsistent deny rule is more problematic because it opens 
up the access on the next restart / for other instances, if done wrong)

The second problem is that if the supervisor wants to automatically 
permit further access to the newly created files, it can only do so by 
remembering and comparing file names, since the new inode doesn't exist 
yet*, and so even with mutable domains there is nothing to attach new 
rules to.  This means that there is a potential for files/dirs to be 
moved/created/linked behind its back onto the destination by someone 
outside the sandbox, and this may result in the supervisor 
unintentionally allowing access to files it doesn't want to? (like, if 
it approves the request based solely on the belief that the file is new)

*: Assuming we don't want to lock the parent dir forever until the 
supervisor replies.

While this does seem like a problem, I'm not sure how practical it would 
be to exploit, since any further action by the sandboxed app itself on 
the destination can/would also be blocked by landlock, and in some sense 
we're already dead if the sandboxed app can somehow convince something 
outside of the sandbox to create arbitrary links or move arbitrary files 
to a destination path that would appear to belong legitimately to the 
malicious app.  But this does raises more questions than I initially 
thought, and shows how an overly creative supervisor may shoot itself in 
the foot -- when filenames are involved in permission decisions the 
semantics starts becoming a bit fuzzy, and is different from current 
landlock which is entirely inode-based.

With that said, I would still really like to make the mentioned UX 
possible tho - allowing an app to create a file/dir and any further 
access to it as well _feels very intuitive_, and is especially 
convenient for cases where the first launch of an app is sandboxed.  But 
I do recognize that this capability is less important for self-sandbox 
scenarios (since the supervisor can pre-create all the scaffolding 
directories it knows the app would need).

I have some thoughts, none of which are perfect, and not doing any of 
them is also an option (i.e. the supervisor just have to decide whether 
to give permission to create files of arbitrary names or not, and can't 
find out about any new files/dirs created (unless with some other Linux 
mechanism)):

1. Maybe there can be a mechanism for the supervisor to be invoked 
post-creation (passing in a fd for the new file directly), then it can 
prompt the user and either allow and optionally add the new inode to the 
mutable domain, or it can "undo" the operation by deleting the new 
file/dir then reject the "request".  I recognize that this is a bit 
weird and is also only applicable to supervise mode, but it might be 
acceptable since merely creating an empty file/dir is relatively 
harmless (ignoring symlinks and device nodes for the moment).

2. The supervisor can create the file/dir/device-node/symlink on behalf 
of the sandboxed app, if we can pass all the relevant arguments to it in 
the request.  Then there needs to be a mechanism for it to tell the 
kernel to return a custom error code to the invoking program.
(seccomp-unotify deja vu)

3. We find a way to implement "allow once" which will only allow this 
particular create request, with this name.  At least this way the 
supervisor can implement the above mentioned feature, with the caveat 
mentioned above.

(For other's reference, I had a discussion with Mickaël and it looks 
like we will want to have mutable domains and base the implementation of 
landlock supervise off that, returning a -ERESTARTNOINTR from the hook 
when access is allowed.  I will write up the discussion tomorrow / later)


>>
>> (I can see this kind of policy being applied to dirs like /tmp or my
>> Downloads folder. $XDG_RUNTIME_DIR is also a sensible place for this
>> behaviour due to the common pattern of creating a lock/pid file/socket
>> there, although on second thought a GUI sandbox probably will want to create
>> a private copy of that dir anyway for each app, to do dbus filtering etc)
> 
> An $XDG_RUNTIME_DIR per sandbox looks reasonable, but in practice we
> also need secure proxies/portals to still share some user's resources.
> This part should be implemented in user space because the kernel doesn't
> know about this semantic (e.g. DBus requests).




More information about the Linux-security-module-archive mailing list