> > 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