tetragon icon indicating copy to clipboard operation
tetragon copied to clipboard

tetragon: print current main tetragon security context from /proc/self/attr

Open tixxdz opened this issue 1 year ago • 11 comments

Early at startup read current security context and print it, this will help debug cryptic errors cases if SELinux, Apparmor are applied to tetragon, even if we are under a seccomp...

tixxdz avatar Aug 25 '22 12:08 tixxdz

Information should be obtained from /proc/self/status, /proc/self/attr/current and related directories inside /proc/self/attr/

tixxdz avatar Sep 13 '22 11:09 tixxdz

Hey @tixxdz, I have been reading up a lot on eBPF space recently and would like to get involved with Tetragon and feel like this will help me start my deep dive into it. Could you help me with what am I supposed to do to solve this issue? Below is my understanding till now:

  • As soon as Tetragon starts, we are supposed to log this information to help us get other 3rd party errors/warnings beforehand itself
  • Now, this information can be found in the directories you have mentioned

However, I'm not clear with the following things:

  • What should and should not be logged?

Also, if you could point me to any resource(article, video, blog) that could help me get a clear understanding wrt this issue/related, I would really really be thankful to you.

Would like to apologize already if I asked any dumb doubt :))

ShubhamPalriwala avatar Sep 27 '22 15:09 ShubhamPalriwala

Hi @ShubhamPalriwala

The aim here is to log security context of Tetragon when it starts. If there are some Linux security module that are active they may restrict Tetragon, this may cause errors and can be hard to debug as probably errors are in the audit subsystem if it is active or in other logs... which are usually not easy to access.

This is mainly help debug Tetragon issue task.

You can start reading about /proc/self/attr format and what's there, then split tasks to print security contexts based on the LSM being used if it's active or not, etc

We want mainly the security context of tetragon in SELinux, Apparmor or any other bit that can be useful to say hey maybe tetragon is restricted in some way...

Just read about https://man7.org/linux/man-pages/man5/proc.5.html , then try to get your way from that ;-)

Any useful information should be logged during startup at info() level

Thanks!

tixxdz avatar Sep 28 '22 15:09 tixxdz

Thank you so much for the detailed information, I've went through a couple of talks:

getting a clear idea of seccomp, AppArmour, and SELinux.

And I just went through the proc man page to understand the whats and hows of it.

According to me, the things that we can log right now can be:

  • /proc/version: Displays kernel deets (eg: Linux version 1.0.9 (quinlan@phaze) #1 Sat May 14 01:51:54 EDT 1994)
  • /sys/kernel/security/lsm: All active linux security kernel modules
    • Based on this, log the details for the respective active kernel modules (eg: AppArmor & SELinux)
  • /proc/self/status: seccomp value and filters
  • /proc/[pid]/attr/current: this file represent the current security attributes of the process
  • /proc/[pid]/seccomp: This file can be used to read the process's seccomp mode setting

I have already learned a whole new lot of stuff so thank you for the detailed feedback. Let me know your thoughts on this approach.

ShubhamPalriwala avatar Sep 30 '22 22:09 ShubhamPalriwala

/proc/[pid]/attr/current: this file represent the current security attributes of the process

Yes, only interested into this /proc/self/attr/ , SELinux then check apparmor directory and get its content, just print it in one liner info() that includes any context that was found if all are unconfined then print it to debug and if none was found then ignore.

Other fields we already do, and for seccomp let's see later

tixxdz avatar Oct 01 '22 09:10 tixxdz

Hey, so I spent most of today on trying to setup AppArmor & SELinux on my local machine (Arch x86). I did manage to be successful with AppArmor but SELinux is not just working as I'm running into a ton of errors :((

Based on this, I have thought of an approach and would like to know your thoughts on it before I think of opening a PR:

	currSecurityAttributes, err := os.ReadFile("/proc/self/attr/current")
	unconfined := "unconfined\n"
	if err != nil {
		log.Fatal("could not fetch the security context: ", err)
	}
	if string(currSecurityAttributes) == unconfined {
		log.Debug("external security configs are unconfined")
	} else {
		log.Println("found external security context for tetragon: ", string(currSecurityAttributes))
	}

The roadblocker that I'm facing right now is that I'm

  • unable to setup SELinux locally to test if this works out as expected and
  • unable to write a policy for AppArmor for which i can test if this is working exactly as it is supposed to.

ShubhamPalriwala avatar Oct 03 '22 14:10 ShubhamPalriwala

So first I guess you still can't have the heavy LSMs stacked and working together, you have to boot with one of them, then boot again with the other... However to try SELinux I would boot a distro that has it by default lik fedora or others... the support to have both them working together may land soon or not! we don't care about that, we just want the values...

Yes something like what you have pasted... read SELinux, you should do same for apparmor directory just get current context , concat the content of both SELinux and Apparmor, do not fatal return an error that we can ignore, follow the same code standards as in other part of tetragon.

Testing this can be hard yes, so just add go unit test for the new function, feed it with random values and with real ones that you can get when booting distros that support these LSMs. Enable labeling, then read values from processes that are properly labeled and use such values to test your new function. This should cover us.

tixxdz avatar Oct 04 '22 11:10 tixxdz

Okay, today I applied a policy to our tetragon binary and enabled AppArmor.

This is what I get when I do the following:

$ pidof tetragon
160599

$ cat /proc/160599/attr/apparmor/current
/home/shubham/Desktop/tetragon/tetragon (enforce)

This is a step forward than yesterday.

Now, when I try to log this in our go, I only get an empty string.

	unconfined := "unconfined\n"

	appArmor, errAa := os.ReadFile("/proc/self/attr/apparmor/current")
	if errAa != nil {
		log.Debug("could not fetch the security context for apparmor: ", errAa)
	}
	if string(appArmor) == unconfined {
		log.Debug("apparmor security configs are unconfined")
	} else {
		log.Println("found external apparmor security context for tetragon: ", string(appArmor))
	}

Output:

time="2022-10-05T19:29:47+05:30" level=info msg="found external apparmor security context for tetragon:  "

Would love if you could help me here with this!

ShubhamPalriwala avatar Oct 05 '22 14:10 ShubhamPalriwala

@tixxdz Could you please help me out with the above whenever you get some time, thanks!

ShubhamPalriwala avatar Oct 14 '22 15:10 ShubhamPalriwala

@tixxdz Could you please help me out with the above whenever you get some time, thanks!

Hi @ShubhamPalriwala sorry for late reply, lot of tasks under hand...

That example seems good, so just englobe this into a function, something like

const Unconfined = "unconfined"'

parse_proc_self_attr() {
       selinux, err, := read_proc_self_attr_security(ATTR_SELINUX, "/proc/self/attr/current")
       
       apparmor, err := read_proc_self_attr_security(ATTR_APPARMOR, "/proc/self/attr/apparmor/current")

       ...

       if selinux != Unconfined || apparmor != Unconfined {
                  Log.WithFields...{ "SELinux": selinux, "AppArmor" : apparmor }).Info("Running with security attributes") 
       }

       return nil
}

Inside read_proc_self_attr_security , you always log.Debug() to make users life easy, when you read strings trim... for why it returns empty, no idea you will have to find out

tixxdz avatar Oct 28 '22 15:10 tixxdz

Hey @ShubhamPalriwala, are you still planning on finishing your draft PR? :)

mtardy avatar Jan 15 '24 11:01 mtardy