[apparmor] Retrofitting & access-control impedance mismatch for MinorFs
John Johansen
john.johansen at canonical.com
Wed Jul 3 07:04:04 UTC 2013
On 06/25/2013 04:27 AM, Rob Meijer wrote:
> On Tue, June 25, 2013 11:35, John Johansen wrote:
>> On 06/24/2013 09:31 PM, Rob Meijer wrote:
>>> On Mon, June 24, 2013 22:22, John Johansen wrote:
>>>> On 06/24/2013 12:16 AM, Rob Meijer wrote:
> ..
>>> That's amazing news. Could the above blocking of access to
>>> /proc/$(pid_other_than_self)/fd/* be easily expressed in such a default
>>> profile?
>>>
>> So the trick to doing this with apparmor 2.x. Is loading policy in the
>> initramfs, and then having early init re-exec it self so it picks up
>> the loaded policy.
>>
>> Like I said it is a real pain
>>
>> You can do that in apparmor3 but it also adds the ability to define a
>> default profile, that can be set as a kernel parameter. That profile
>> starts in "unconfined" mode but can be replaced and start enforcing
>> policy. Which allows us to get the policy load out of initramfs into
>> early boot and is adequate if you trust your early boot process
>>
>>>>
>>>>>
>>>>> I would really like to hear the thoughts of others on this
>>>>> mailing-list
>>>>> on
>>>>> this. Should I give up on combining a retrofit version of MinorFs with
>>>>> the
>>>>> non-retrofit features of decomposition, attenuation and delegation?
>>>>> Should
>>>>> I add the confinement check for CapFs access or is this a futile
>>>>> addition
>>>>> that is to easily bypassed? Or should I just provide a massively
>>>>> permissive profile that could be used for all currently unconfined
>>>>> processes and allows almost everything except for the specific places
>>>>> under /proc where sparse-caps could be stolen?
>>>>>
>>>> So if I was to do the restrictions via apparmor I would make a default
>>>> profile
>>>> and disallow access to the special files. Any process that needs access
>>>> to
>>>> a token file is under a different profile. So tighter than what you
>>>> propose
>>>> above, and you can have fairly loose special profiles that have access
>>>> to
>>>> a subset of the special files.
>>>>
>>>> I need to reread so of the minorfs details again before I could propose
>>>> a
>>>> solution in greater detail.
>>>
>>> My problem is that if we have 3 processes running under the same uid:
>>>
>>> Alice: AppArmor confined, pid=1000, has been delegated a process private
>>> directory by MinorFs that is freely accessible trough
>>> /minor-mnt/cap/rw-3ffc8f682cfab4f753d32a9182ebbe8e30e34e19/
>>> Alice has the following file currently open:
>>> /minor-mnt/cap/rw-3ffc8f682cfab4f753d32a9182ebbe8e30e34e19/foo.xml
>>> Bob: An other process, AppArmor confined, pid=1001, not programmed in
>>> a
>>> way that makes it aware that it might be acting as a deputy. Bob
>>> can
>>> not readlink /proc/1000/fd/*.
>>> Mallet: An unconfined 'trojan' process, pid=1002. Mallet can readlink
>>> /proc/1000/fd/* and so 'steal' the sparse-cap to the private
>>> directory of Alice.
>>>
>>> The ultimate solution is to keep Malet from stealing the sparse-cap.
>>> An other alternative is to make /minor-mnt/cap/* inaccessible to Malet
>>> by adding access control to the file-system that denies any access to
>>> unconfined processes. This alternative however turns Bob into a
>>> potential
>>> confusable deputy. A third solution is to delegate trough an overlay
>>> filesystem. This third solution however has major performance cost and
>>> takes away the the ability to decompose,attenuate and delegate ones
>>> private storage sub-tree to other processes.
>>>
>>> If as you hinted the ultimate solution of a default 'deny sparse-cap
>>> stealing' policy would be possible, this would take away the need to
>>> choose between two relatively disagreeable options.
>>>
>> right so a default profile could provide the ability to deny access to
>> /minor-mnt/cap/*
>
> Yes, but ideally the default policy (and most specific policies) could
> deny access to something like @{PROC}/@{OTHERPID}/fd/*, that would solve
> the whole problem.
>
> Alternatively if/as-long-as this isn't possible either the default policy
> or the CapFs file-system could deny access to /minor-mnt/cap/*, but as
> stated this would result in the confused deputy issues as remaining
> potential problem.
>
>> Its a matter of how to setup this default. It can be done
>>
>> system wide:
>> - From early boot by specifying the default profile (hard in 2.8)
>> - Approximated with an early loaded default profile with attachment
>> specification (this technique changes pix, and pux behavior from
>> what would be had with the unconfined profile). Also processes
>> started before the profile remain in the unconfined state.
>>
>> eg.
>> profile default /** {
>> deny /minor-mnt/cap/* rw,
>> ...
>> }
>>
>> This will attach to any executable but if a profile with a more
>> specific match is provided it will match first.
>>
>> per user:
>> - pam_apparmor can be used to provide a default profile for each
>> user. So that the profile can be unique to the user.
>>
>>
>> I feel like I am still missing something, as I am not fully understanding
>> the confused deputy case.
>>
>
> Basically I think there would 3 distinct possibilities:
>
> 1) The default policy you describe helps to keep any non-special process
> from doing a readlink on @{PROC}/@{OTHERPID}/fd/*. This would solve the
> whole issue. No performance price. No sacrificing functionality.
> No confused deputies.
right so this isn't possible atm but we are working on it. Specifically we
do have a plan, and I have been gradually working on it. It requires improvements
to the compiler and matching engine, and we don't have it scheduled to land
in the up coming 3.0 release.
It is a possibility for the following 3.1 release in the spring.
> 2) CapFs is made to only allow /minor-mnt/cap/ access to higher lever
> MinorFs file-systems and these file-systems work as overlay file-system.
> There is no authority leakage possible, but there is a performance issue.
> Next to this, the ability to decompose,attenuate and delegate ones
> private storage sub-tree to other processes is sacrificed.
right
> 3) Either the default policy or the CapFs file-system could deny access to
> /minor-mnt/cap/*. This leaves open the confused deputy issue, but doesn't
> have the performance or functionality price of 2.
>
Could you live with this solution until 1 is complete?
> The issue with 3 would be that Malet could readlink for example
> /proc/1000/fd/5 and gain access to the pseudo path for Alice her private
> directory. Malet couldn't access this path herself, but Bob could. If
> Malet can convince Bob to access the file on her behalf, than we have a
> confused deputy problem.
>
> I think its fair to conclude that '1' is the preferred option, and that
> this preferred option depends on (at-least) AppArmor version 3 to be
> sufficiently secure. Will AppArmor 3 allow expressing something like a
> deny for @{PROC}/@{OTHERPID}/fd/* in a default policy? If so, what order
> of magnitude timescale are we looking at for version 3?
>
So again 3.0 won't have this but I have been working on it. 3.0 is scheduled
to land this fall, feature freeze around the start of September and ship
in mid October.
Will be the 6 month followup and is scheduled for the spring of next year.
I wish I could say that we will have @{pid} and the other kernel vars
support for 3.0 because it would solve several problems, not just for
minorfs but with the current set of work we still have to get done.
I don't see it happening, and the planning is currently for 3.1
More information about the AppArmor
mailing list