Hi John, Seth,

Thanks again for the details. I would like to get your inputs and clarify
my understanding.
Please go through the trailing email and correct me if I am wrong.

*Goal:* Reducing root permission of the process and enabling required
capabilities for the process.

*Design and approach:*

- To identify the required CAPs for the process, we are planning to enable
all CAPs while running in "non-root"
  mode and from apparmor logs, hopefully we would be able to find the
required capability list for the process
  specific.

- Please note that our user "non-root" (UID) is fixed. we won't change the
user UID and GID for non-root.

*Implementation:*

- Process would be starting as "root" and dropping to non-root then
applying required CAPs based on above apparmor logs
  using libcap APIs.

- Most of the process needs CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH to
read/write root privilege files/directories.

*Query specific to above non-root approach: *

- We are planning to enable CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH CAPs when
the process switches to non-root.
- Then based on a process for example network specific process, we will
enable CAP_NET_ADMIN.
- In case of system specific processes to access hardware details, we will
enable CAP_SYS_ADMIN.
- Please note, we will require CAPs based on apparmor logs as indicated
above.

Here, the doubt is that if we enable CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH,
CAP_NET_ADMIN, CAP_SYS_ADMIN to run
the process in non-root to ensure it works in the same way when it was
running in "root".

Do you think enabling CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_NET_ADMIN,
CAP_SYS_ADMIN in the process
are we missing any security or this is expected while using Linux
capabilities for non-root (dropping root privilege).

Please share your valuable suggestions on security specific views.

*General query:*

- Is Linux capabilities belong to DAC or LSM/MAC?
As per my understanding, Linux capabilities are part of LSM. But I still
think that few CAPs are used in DAC.
Please share the details with example.

- Is LSM mandatory to enable in Linux Kernel?

- Which LSM is enabled in linux by default?

- Why do we need MAC as we have a security check by discretionary access
controls (DAC) ?
Is MAC mandatory to enable or optional?

- Is MAC really mandatory for Linux? AS per my understanding, for embedded
linux devices no need to enable MAC on production devices.

Thanks
Murali.S

On Wed, Aug 5, 2020 at 3:25 AM John Johansen <john.johan...@canonical.com>
wrote:

> On 8/4/20 7:46 PM, Murali Selvaraj wrote:
> > Thanks for the explanation.
> >
> > Goal: Converting root process to non-root process by enabling required
> capabilities for the process.
> >
> > Scope: Am trying to find out required capabilities for the process which
> is going to run as "non-root"
> >
> > How to use Apparmor to find the capabilities specific to process:
> >
> > -> As per above discussion, Apparmor does not grant the required
> capabilities.
> >
> > -> We had thought that, from apparmor logs, we would be able to find the
> required capabilities.
> >
> > -> To find this, we would be following the steps to find the
> capabilities.
> >
> > Process (A) will be running in "non-root" but with all enabled
> capabilities and check the apparmor logs.
> > Apparmor logs will show the required capabilities.
> > Capture these CAPS and use this CAPS in the process code to convert that
> process root to non-root by only enabling this CAPs observed in apparmor
> logs.
> >
> > Is above understanding correct? please confirm the steps if anything is
> missing.
> >
>
> Yes AppArmor with the caveat that the "non-root" user is the one you plan
> to use in the future. Any "non-root" user will likely work but I can't
> guarantee it unless you use the same uid.
>
>
>
>
>
> > *General Query:*
> >
> > In any event, AppArmor will usually see capability requests after the
> usual DAC permissions are handled.
> >
> > Can you please explain this above statement with simple example?
> >
>
> The kernel applies multiple checks (eg. input validation) and the kernel
> bails on the first failed check. A pseudo code of this idea is
>
>   fn () {
>
>     if (input bad)
>        return fail;
>
>     if ( task uid != object uid) {
>        if ( not capable (CAP))
>          return fail;    }
>     if ( not APPARMOR_CAP(CAP))              <---- AppArmor will log if we
> get here
>        return fail;
>   }
>
>
> The kernel generally does multiple checks like explained in the pseudo
> code above. The general pattern is the same as in the pseudo code too. That
> is input validation comes first, then object lookup, then DAC based
> permission check (regular unix capability and uid checks), and then the LSM
> (apparmor) based checks.  But code gets grouped into reusable fns and some
> time fn order can result in a MAC (apparmor) happening before the DAC check.
>
> The overlarching pattern is DAC comes first but there are a few cases
> where AppArmor is checked first, however you can be assured all required
> checks will happen.
>
>
> > For example, Process (x) tries to open a file (/etc/security) which is
> root permission but the process (x) runs in "non-root mode.
> > Pls note, process (x) does not have permission to open this file
> ((/etc/security) )
> >
> > open => sys_open() => kernel further code for handing the code.
> >
> > sys_open() => will return permission denied error due to permission
> issue.
> >
> > Here, capable() check won't happen. Does DAC take care of this check
> without using capability (CAP_DAC_READ_SEARCH)?
> >
>
> yes DAC includes uid and guid checks. The capability call for
> CAP_DAC_READ_SEARCH only happens if the uid/guid checks fail.
>
> > In such a case, trying to understand when Kernel uses capable() to check
> CAP_DAC_READ_SEARCH/CAP_DAC_OVERRIDE before/after DAC.
>
> these capabilities are only checked if the uid/guid check fail, in which
> case the task will need these capabilities to access the file
>
> ie. if you own the file you don't need CAP_DAC_OVERRIDE
>     if you are in a group that allows access to the file you don't need
> CAP_DAC_OVERRIDE
>
> > Can you please explain the relation between DAC, apparmor and linux
> capability with this context?
> >
>
> Its generally follows the pattern outlined in the pseudo code above, but
> the pattern does vary with the hook and object. The reality is more
> complicated than the pseudo code.
>
> There are hooks where you get multiple DAC checks (uid and cap) an
> multiple LSM checks. Eg. some file operations will be closer to the pattern
>
>   input validation
>
>   object lookup
>      loop on path elements
>         DAC uid check
>            DAC capability check
>               MAC capability check
>      MAC inode check
>
>   MAC path check
>
>   MAC inode check
>
>
> so there are potentially checks on every element of the path walk, and
> also checks at the operation type (eg. mmap, chown, ...)
>
>
>
> > Thanks
> > Murali.S
> >
> > On Tue, Aug 4, 2020 at 6:08 AM John Johansen <
> john.johan...@canonical.com <mailto:john.johan...@canonical.com>> wrote:
> >
> >     On 8/3/20 8:02 PM, Murali Selvaraj wrote:
> >     >
> >     > Hi Seth,
> >     >
> >     > Thanks for the detailed explanation. Please go through below
> details and clarify further queries.
> >     >
> >     > I do not see a capability difference when this script runs in root
> (UID:0)  and nobody (UID>0).
> >     > If we are observing the required capabilities when the script runs
> in root, that would be easy for us to find
> >     > the needed capabilities for this script. Then we will apply this
> capability when it runs in nobody user.
> >     >
> >     > #!/bin/sh
> >     > echo "Testing"
> >     > while [ 1 ]
> >     > do
> >     > cat /etc/foo   =================> Ensure this file belongs to root
> permission
> >     > echo "TESTING" > /nvram/foo
> >     > killall <root_process_name>
> >     > sleep 5
> >     > done
> >     >
> >     >  ls -ltr /etc/foo
> >     > -rw-r--r--    1 root     root             8 Aug  3 20:31 /etc/foo
> >     >
> >
> >     can you please add
> >
> >     echo -n "Confinement:"
> >     cat /proc/self/attr/current || echo "Failed to obtain confinement" ;
> exit 1
> >
> >     to your script after the killall or something similar, this will
> dump the confinement of the "cat" command but unless you have a transition
> for "cat" it should have the confinement of it parent or be denied.
> >
> >     I should note that apparmor does have a dedup cache around logging
> capabilities. It is a single entry per processor (or virtual processor),
> and will prevent a previously seen cap from being logged IFF no other
> PROFILE has mediated a cap on that processor since the last time that
> profile previously logged the CAP in question.
> >
> >     There is no manual switch to clear the cache, but it can be
> effectively cleared by replacing the profile but you need to actually make
> a change to the profile so that profile load dedup doesn't drop the
> replacement.
> >
> >
> >     >
> >     > Can you please check this script in your environment and share
> your observation. Please do the needful.
> >     > Please execute in root and non-root mode and find the capability
> list from apparmor log events.
> >     >
> >
> >     not exactly your script but roughly equivalent
> >
> >     unconfined non-root user killing root process
> >
> >       $ kill 23579
> >       bash: kill: (23579) - Operation not permitted
> >
> >     no apparmor log message.
> >
> >     ----
> >
> >     unconfined root user killing root process
> >
> >       $ sudo kill 23579
> >
> >     success, no apparmor log message
> >
> >     ----
> >
> >     confined non-root user without signal or CAP permissions killing
> root process
> >
> >       $ aa-exec -p demo -- kill 23965
> >       kill: (23965): Operation not permitted
> >
> >     no apparmor log message
> >
> >     ----
> >
> >     confined root user without signal or CAP permissions killing root
> process
> >
> >       $ sudo aa-exec -p demo -- kill 23965
> >       kill: (23965): Permission denied
> >
> >     apparmor log messages
> >
> >     [987021.379719] audit: type=1400 audit(1596533293.878:234):
> apparmor="DENIED" operation="signal" profile="demo" pid=24036 comm="kill"
> requested_mask="send" denied_mask="send" signal=term peer="/usr/bin/man"
> >     [987021.379727] audit: type=1400 audit(1596533293.878:235):
> apparmor="DENIED" operation="signal" profile="/usr/bin/man" pid=24036
> comm="kill" requested_mask="receive" denied_mask="receive" signal=term
> peer="demo"
> >
> >     notice no capabilities are needed to send the signal because its
> being sent from root to a root process
> >
> >     ----
> >
> >     confined root user without signal or CAP permission kill a non-root
> process (different uids)
> >
> >       $ sudo aa-exec -p demo -- kill 24690
> >       kill: (24690): Operation not permitted
> >
> >     apparmor log message
> >
> >     [989073.431936] audit: type=1400 audit(1596535345.981:238):
> apparmor="DENIED" operation="capable" profile="demo" pid=24717 comm="kill"
> capability=5  capname="kill"
> >
> >     finally we get a CAP request for kill
> >
> >
> >     The reason for this is that the kernel applies DAC mediation before
> LSM (apparmor) mediation. AppArmor never sees the permission request unless
> DAC allow the operation.
> >
> >     > *Need further clarifications:*
> >     >
> >     > My aim is to identify the required capabilities for the process
> when it runs in "non-root" user.
> >     > Currently, this process runs in root mode, so by default all CAPs
> are enabled in Effective/Permitted CAPs.
> >     >
> >     > Analysis:
> >     >
> >     > -> While the process runs in non-root mode, we are planning to
> apply the capabilities before switching to non-root from root.
> >     >    So, we need to set appropriate capabilities in order to run the
> application successfully in "non-root".
> >     >
> >     yes
> >
> >     > -> As per my assumption, we will find the required capabilities
> when the process runs in root-mode. To find the required CAPs list
> >     >    we thought to use "apparmor" logs while the process runs in
> compliant mode.
> >
> >     this doesn't quite work but you will be able to collect capabilities
> that don't rely on a uid check. This is because of how the kernel doesn't
> always apply a capability check, Eg. for kill CAPS are not always checked
> in the same way when subject uid == object uid vs. subject uid != object
> uid. The same can be said for DAC_OVERRIDE, DAC_READSEARCH, ...
> >
> >     Some capabilities however aren't guarded by uid checks and you
> should be able to collect these caps when run as root. What you need to do
> to collect the full list of capabilities is give the non-root process all
> capabilities and run it. This should collect the full set of CAPs with how
> you are using uids.
> >
> >
> >     >    Once we get the CAPs list from Apparmor logs, then we shall use
> the same required CAPS only ( NOT all the CAPs) for the
> >     >    process when it runs in non-root mode.
> >     >
> >     > -> The idea is that we are trying to drop root privilege using
> this method.
> >     >
> >     > Can you please confirm , the above method is possible in apparmor
> event logs to find the required CAPs at least when run
> >     > in "root" mode.
> >     >
> >
> >     close but see above, also you need to make sure exercise the
> application to get proper coverage
> >
> >     > Thanks
> >     > Murali.S
> >     >
> >     > On Mon, Aug 3, 2020 at 8:21 PM Seth Arnold <
> seth.arn...@canonical.com <mailto:seth.arn...@canonical.com> <mailto:
> seth.arn...@canonical.com <mailto:seth.arn...@canonical.com>>> wrote:
> >     >
> >     >     Hello Murali,
> >     >
> >     >     On Mon, Aug 03, 2020 at 02:03:38PM -0400, Murali Selvaraj
> wrote:
> >     >     > Query 1:
> >     >     >
> >     >     > - But I do not see CAP_DAC_OVERRIDE and CAP_KILL in apparmor
> event logs.
> >     >
> >     >     AppArmor does not have a mechanism to grant capabilities that
> a process
> >     >     does not already have. The kernel will query LSMs to see if a
> capability
> >     >     is allowed to be used if the process already has the
> capability in
> >     >     question. (There may be exceptions to this, there's hundreds
> of these
> >     >     checks scattered throughout the kernel.)
> >     >
> >     >     You'll only see these requests in AppArmor logs if the process
> had these
> >     >     capabilities. By using su to switch to the 'nobody' account,
> you only have
> >     >     access to whatever privileges the nobody account already has:
> additional
> >     >     access to root_squashed files on NFS, any other processes
> mistakenly
> >     >     running as user nobody, etc.
> >     >
> >     >     Because this doesn't include any capabilities in the process's
> >     >     capabilities sets, AppArmor won't even see the requests.
> >     >
> >     >     > Query 2:
> >     >     >
> >     >     > - How apparmor identities how many capabilities are needed
> for the process?
> >     >
> >     >     The kernel will call capable() in the codepaths as necessary;
> the security
> >     >     module interface will get the calls, without context, after
> the rest of
> >     >     the kernel's capabilities handling. It's difficult to follow
> because it's
> >     >     been heavily optimized for performance.
> >     >
> >     >     In any event, AppArmor will usually see capability requests
> after the
> >     >     usual DAC permissions are handled.
> >     >
> >     >
> >     >     > Query 3:
> >     >     >
> >     >     > - Does all system calls need capability when it runs in a
> non-root process,
> >     >     > how does apparmor mapping the linux capabilities?
> >     >
> >     >     "root processes" means both uid 0 as well as having
> capabilities in the
> >     >     effective capability set. (Perhaps it'd also make sense to
> consider the
> >     >     other capability sets in the process?) A uid 0 process with no
> >     >     capabilities still has considerable power, since many
> important files like
> >     >     /etc/sudoers are owned by uid 0, and modifying these files
> through DAC
> >     >     permissions alone could be used to then gain capabilities.
> However, a uid
> >     >     0 process with no capabilities couldn't itself initiate a
> reboot in the
> >     >     kernel, or override DAC restrictions on files, etc.
> >     >
> >     >     A process with capabilities need not be uid 0 though I can't
> immediately
> >     >     point any common examples.
> >     >
> >     >     Linux's uid namespaces makes things a bit more complicated: a
> process can
> >     >     have namespace-level capabilities that do not extend to
> capabilities in
> >     >     the init namespace. (Consider something like an LXD guest:
> there may be
> >     >     different users within the guest, and the 'root' user with the
> LXD guest
> >     >     can do privileged operations over the namespace, eg manage the
> routing
> >     >     table used for that network namespace, but not be able to
> manage the
> >     >     routing table used by the network namespace for the init
> process.)
> >     >
> >     >     See the user_namespaces(7) and unshare(2) manpages for some
> more information.
> >     >
> >     >     > Can someone please clarify these queries?
> >     >
> >     >     I'm afraid my description probably made things worse.
> >     >
> >     >     Let me try one quick simple thing:
> >     >
> >     >     Run your example with and without root privileges. You'll see
> the
> >     >     difference in AppArmor log output. Hopefully that helps. :)
> >     >
> >     >     Thanks
> >     >
> >     >
> >
>
>
-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to