Mitigating risks, part 1

We are running Foobar 2.0 on Tomcat 4. We know that Tomcat 4 isn’t supported, but hey – our (internal) customer is happy that the Foobar application works and would like to keep it that way. Upgrading to Tomcat 5 or higher is not possible – Foobar 2.0 only works on Tomcat 4. If we want to use a higher Tomcat version, we need to upgrade the application which costs a lot of money (which our (internal) customer doesn’t want to pay) and requires lots of testing as it is a non-trivial upgrade. So… what can an IT department do to mitigate the risks here?

This is not a hypothetical example (well, apart from the software titles used) for many organizations. Be it the application itself, its middleware, back-end or operating system: often you’ll face an end-of-support deadline without the means to upgrade the application (because of budgetary issues, unwillingness of the responsible department or no alternative). Whatever the reason, you as an IT department have the responsibility to mitigate the risks involved with running out-of-support software (and communicate risks to all parties that are affected by it). So what are your options?

In this series of posts, I’ll cover a set of risk mitigation strategies that might help you reduce the issues that come up from running out-of-support software. But first, what are those risks?

  • Security patches. It is the first risk that the operations department will say when they have to deal with unsupported software. Well, the risk isn’t the security patches, but the result made by the lack of it. Software tends to have bugs. Some of these bugs can result in inappropriate functionality, such as granting access to unauthorized people or even executing (unwanted) commands on the server. Sounds improbable? Guess again. Especially when running out-of-support software this becomes a nightmare to manage, because security patches are not created anymore, and newly discovered vulnerabilities might still affect older versions – even when the vulnerabilities do not mention the older versions anymore. And the worst thing is that you might not even detect it.
  • Functional bugs. If your customer tries something out and the application barfs, then there is little you can do to fix this. Either you dive in the code yourself (good luck with that) or you hope that a workaround exists. Getting a functional bug fix is not that feasible. Also, do not think that functional bugs will not pop up anymore “because the application has been running fine for years”. A change on the system (update of the java runtime, kernel upgrade, update on a particular library) might be enough to trigger it.
  • Non-functional bugs. The application starts dragging down? You notice inflated response times? Can the application only deal with 10 concurrent users, but your customer just hired 2 additional employees? Too bad. You might be able to work around this by duplicating the application and putting a load balancer in front of it, but with stateful applications that isn’t always that easy to
    accomplish. Forget about service level agreements when the software is unsupported. You can’t guarantee them anymore.
  • Legal requirements. You might not know it, but many institutions are governed by specific IT requirements. Especially the financial sector (with the recent crisis and all) is and will get more and more regulatory compliance requests, and the IT infrastructure will not be spared. If you run unsupported software, you might be ignoring particular requirements that you have.
  • Upgrade difficulties. Eventually you will need to upgrade. If the software you are upgrading from is unsupported, chances are very low that a good, flexible (and cost-efficient) upgrade trajectory exists. Migration scripts will probably not work and consultancy will fail. Anyone have experience with upgrading from Oracle 7.3 to Oracle 11g?
  • Integration failures. Most applications are integrated in a larger architecture. Applications probably get authorization feeds or send out events to other components. As the external services that the application interacts with get updated, their interfaces update with them. And eventually you will get into a situation where the integration suddenly fails. I’ve seen an application use HTTP/1.0 whereas its external services suddenly only supported HTTP/1.1. Have fun explaining that to your customer (who might not even know that HTTP is a protocol).
  • Customer support. If you use an internal help desk, then you might be able to educate them with troubleshooting the (unsupported) software. But if the help desk is external, you’ll probably be facing a “No” after a while – or a nice additional fee.

Some of these risks not only affect the product itself, but all other products / softwares that are installed on the server (or even on the network). If you ever face the request to continue supporting Foobar 2.0 on an unsupported Tomcat, now you have a checklist that you can tell your (requesting) customer about the risks he is introducing – and don’t forget to tell the other customers about the risks they will be taking as well then.

But I promised that I will be talking about risk mitigation… so just hold on for part 2 — “service isolation”.

Posted in Architecture, Security | 1 Comment

Now using refpolicy 2.20110726

A few days ago, I committed the SELinux policy modules that are based on the 2.20110726 set released upstream. For those that are using Gentoo Hardened with SELinux, you’ll find them if you use the ~arch set for the sec-policy category.

When I talk about upstream, it usually is the reference policy as maintained by Tresys. This project, often abbreviated to refpolicy, tries to maintain a set of SELinux policies that are useful for the majority of Linux distributions. In fact, most (if not all) Linux distributions that support SELinux base their policies on the refpolicy.

Now maintaining a reference policy for SELinux is not that easy, even with the contributions of many distributions and developers. Since the policy is used for many distributions (including RedHat Enterprise Linux) it is vital that presented changes are only accepted if truly necessary (and do not present additional security risks). That means that patches should be well documented and easy to read. Patches that lack a proper motivation and that are not trivial are not accepted.

When distributions want to push updates on the policy to the refpolicy, they need to send the patches to the refpolicy mailinglist. There they are picked up and analyzed and eventually added to the release.

For Gentoo Hardened’s SELinux project, getting (the majority of) our own patches in the reference policy is important, mainly because we currently lack the manpower to maintain a huge patch set ourselves. Every time a new release is made by the reference policy, we need to re-apply (and redevelop) our own patches. For a small set of patches, this isn’t a lot of work, but the more changes you include, the more time-consuming this “patch forwarding” becomes. Of course, by quickly pushing out our patches we also get the confirmation (or rejection) of the patch, allowing us to be certain that we are on the right track. After all, it is a security policy that we are talking of.

Now, the reference policy is just one of “our upstreams”. A second important project – also governed by the Tresys organization – is what is called the SELinux Userspace. This project maintains the tools necessary to build the SELinux policy from readable text for humans to interpretable binary blobs for the Linux kernel. It maintains the tools that help us modify the policies’ runtime behavior (using conditionals), manage file contexts and more. As this tool interacts intimately with the SELinux internals, development of these tools is discussed on the SELinux mailinglist offered by the NSA.

It is the SELinux userspace project that provides tools like semanage, semodule, restorecon, chcon, etc.

So next time you hear me talk about upstream, you know what it is.

Posted in Hardened, SELinux | Leave a comment

Use parted for large partitions

A few bugs that were sitting in Gentoo’s bugzilla for the documentation were related to large partitions (2 TB and higher). Previously, this wasn’t as much as an issue since the number of users that have 2+ TB partitions are fairly slim. But of course time flies, hardware becomes cheaper and I have large partitions myself now too. So we had to update the docs.

Since yesterday or so, the Gentoo Handbook now provides instructions on using parted for partitioning the disk (not for all architectures yet since I can’t validate if it works on those as well). The use of the parted command, which is in the minimal LiveCDs for some time now, allows users to create GPT partition labels (instead of the old-style msdos ones). This partition system, which is supported by other operating systems as well, does not stop at 4 primary partitions, and supports partitions of a size I can currently only dream of (somewhere in the exabytes if I am not mistaken).

Posted in Gentoo | 2 Comments

Easy documentation updates thanks to the many contributions

As mentioned previously, I took a stab at the Gentoo Guide to OpenLDAP Authentication, updating its configuration settings as well as give an introduction to its replication mechanism. Although I am no OpenLDAP guru at all, I set up a similar architecture for testing some SELinux policy changes. This test environment grew (okay, it’s all KVM guests, so the only thing that grew was my resource consumption) and is currently entailing over 24 systems, ranging from BIND (in master/slave) to Apache/Nginx setups, reverse proxies to database clusters and what not.

I’m hoping that I can manage the scripts I use to create those images (perform unattended installations of all these softwares as well as configuration aspects) and eventually provide some more documents for Gentoo on these matters. But until then, I’ll focus more on fixing and helping the publication of documentation (a small list of changes contributed by various people are in the Gentoo Handbook which finally mentions ext4, has seen a whole slew of OpenRC fixes and updated kernel configuration information, or the Gentoo Guide to Mutt which has been rewritten from scratch). If you notice any errors or needs for corrections on Gentoo documentation, don’t hesitate to file a bugreport or drop by on IRC’s #gentoo-doc channel.

Speaking of documentation, the SELinux Handbook has seen a few updates as well, and I have also started pushing some module-specific information (for instance on Portage). This might help some users with their quest to get a particular software title to work on their system with the SELinux policies in place.

Next to the documentation, you’ll also find the SELinux policy modules based on the 2.20110726 version of the reference policy in the hardened-dev overlay. The base policy is currently in revision 2 with revision 3 on the way (asterisk, mutt and mozilla fixes). It now uses a cleaner patching process, something that is also part of the updated selinux-policy-2.eclass. I’m also hoping that I can introduce delivery of the SELinux policy interface documentation (a nicely formatted set of HTML pages showing which kind of interfaces – calls or privilege “bundles” if you like – are available), of course based on the availability of USE=”doc”.

Once this has been accomplished, I’ll see that the new policy modules are migrated from the hardened-dev overlay to the main tree. Also, the majority of changes made to the policy are since revision 2 of the base policy in a more manageable format, allowing for faster pushing of the changes to the upstream reference policy.

Posted in Gentoo, Hardened, SELinux | Leave a comment

Ready, set, commit!

Yesterday, I have entered the realms of Gentoo Development again. But as it was getting late then, I had to wait before the first commits happened. So this evening, things were done. The first couple of documentation bugs (mostly related to OpenRC) have been committed to the Gentoo CVS repository and I’ve also committed my first change on the gentoo-x86 CVS repository (a small change for the SELinux eclass, needed for the upcoming storm of packages.

So what does that mean for Gentoo and Gentoo Hardened? Well, that means that I’ll be taking on bugs myself now. You can ping me for documentation changes as well as SELinux policy changes. Within the next few hours, a little over 200 packages will be sent to the hardened-development overlay, containing the SELinux policy modules based on the upstream 2.20110726 release. These will linger there for a while, since I had some troubles getting them into the shape they are now – so some additional testing doesn’t hurt.

During the testing, most of the patches applied will also be submitted upstream for verification and inclusion. Simultaneously, a second set of patches will be prepared to squeeze out the remaining issues that are either left, or that have been reported since the push (I am expecting quite a few still, but luckily many users on #gentoo-hardened are helping out in testing SELinux).

While we are on the SELinux policy development, I’ll also be handling a few other documentation bugs. I’m hoping to take a stab at Gentoo’s OpenLDAP HOWTO since I’ve been running a similar setup here for some time (including SELinux support of course ;-)

Speaking about documentation, Anthony G. “blueness” Basile has pushed some documentation updates that I made in the hardened-docs repository to the main site. That means that users can now see how Gentoo Hardened supports MCS (and even talks about MLS for the brave ones out there). And since we now support MCS and have the latest userspace utilities in our repository, we can finally see if we can support SELinux sandboxing, a functionality that is already available in Fedora/RedHat but not fully supported through the upstream channels yet.

Posted in Hardened | 2 Comments

checksec kernel security

I have blogged about checksec.sh earlier before. Jono, one of the #gentoo-hardened IRC-members, kindly pointed me to its --kernel option. So I feel obliged to give its options a stab as well. So, here goes the next batch of OPE-style (One Paragraph Explanations).

~# checksec.sh --kernel
* Kernel protection information:

  Description - List the status of kernel protection mechanisms. Rather than
  inspect kernel mechanisms that may aid in the prevention of exploitation of
  userspace processes, this option lists the status of kernel configuration
  options that harden the kernel itself against attack.

  Kernel config: /proc/config.gz

  GCC stack protector support:            Enabled
  Strict user copy checks:                Enabled
  Enforce read-only kernel data:          Disabled
  Restrict /dev/mem access:               Enabled
  Restrict /dev/kmem access:              Enabled

* grsecurity / PaX: Custom GRKERNSEC

  Non-executable kernel pages:            Enabled
  Prevent userspace pointer deref:        Disabled
  Prevent kobject refcount overflow:      Enabled
  Bounds check heap object copies:        Enabled
  Disable writing to kmem/mem/port:       Enabled
  Disable privileged I/O:                 Enabled
  Harden module auto-loading:             Enabled
  Hide kernel symbols:                    Enabled

* Kernel Heap Hardening: No KERNHEAP

  The KERNHEAP hardening patchset is available here:

https://www.subreption.com/kernheap/

In-kernel GCC stack protector support is the same as the Canary explanation I gave earlier, but now for the kernel code. Memory used by the stack (which contains both function variables as well as return addresses) is “interleaved” with specific data (canaries) which are checked before using a return address that is on the stack. If the canary doesn’t match, you’ll see a nice kernel panic. This is to prevent buffer overflows that might influence the in-kernel activity flow or overwrite data.

When talking about Strict user copy checks, one can compare this with the FORTIFY_SOURCE explanation given earlier. Although not the same implementation-wise (since the latter is gcc/glibc bound, whereas the Linux kernel does not use glibc) this too enables the compiler to detect function calls with variable length data arguments to an extend that it can predict the (should-be) length of the argument. If this is the case, the function is switched with a(nother in-kernel) function that either continues the call, or break in case of a length mismatch. This is to prevent buffer overflows that might corrupt the stack (or other data locations).

Enforce read-only kernel data marks specific kernel data sections as read-only to prevent accidental (or malicious) manipulations.

When selecting Restrict /dev/mem access, the kernel does not allow applications (even those running as root) to access all of memory. Instead, they are only allowed to see device-mapped memory (and their own process memory). The same goes for Restrict /dev/kmem access, which is specifically for kernel memory.

Non-executable kernel pages is similar to the NX explanation given earlier. It makes sure that pages marked as holding data can not contain executable code (and will as such never be “jumped” in) and pages marked as holding code will never be written to.

To explain Prevent userspace pointer deref, first you need to understand the difference between a userland address and a kernel address. Each application holds its own, private virtual address space. Part of that virtual address space is “reserved” for most of the kernel data (in other words, the kernel data is available in each process’ virtual address space), the rest is for the application. When interaction with the kernel occurs, a userland address is given to the kernel, which needs to translate it to a proper address (and treat it as data). With Prevent userspace pointer deref, specific checks are made to ensure that the kernel doesn’t directly use userspace pointers, because that could be exploited by (malicious) software to trick the kernel into doing things it shouldn’t.

Reference counters in the Linux kernel are used to track users of specific objects or resources. A “popular” way to mistreat reference counters (or any counter per se) is to increment them that much until they overflow and wrap around, setting the counter to zero (or a negative number), leading to unexpected results (such as freeing memory that is in use). The Prevent kobject refcount overflow detects this for kobject resources and ensures that no wrap-around happens.

The Bounds check heap object copies checks if particular memory copies use memory fragments within proper bounds. If the memory copy is for a fragment that crosses that bound (for instance because the fragment is too large) the copy fails. This offers some support against overflows, similar to (but not the same as) the use of the stack protector mentioned above.

Disable writing to kmem/mem/port is similar to the Restrict /dev/(k)mem access settings, plus disable /dev/port from being opened.

By selecting Disable privileged I/O, access to the kernel through functions like ioperm and iopl is prohibited. These functions are sometimes used by applications that need direct device access, like Xorg, but if you do not have such applications, it is wise to disable privileged I/O access. If not, any vulnerability in such an application might result in malicious code tampering with your devices.

When Harden module auto-loading is set, processes that do not run as root will not be able to have particular kernel modules auto-loaded. Although this seems strange, it isn’t. Suppose you have an application that wants to perform some IPv6 actions. Such applications can call request_module to ask the Linux kernel to load in a particular service. If the kernel supports IPv6 through a module, then it will load IPv6 support (you might have seen traces in your logs about net-pf-10 – well, that’s the IPv6 support). You can disable auto-loading completely, but that might not be what you want. With this setting enabled, auto-loading is supported but only for root-running applications.

The added security of Hide kernel symbols is not to prevent activities, but to prevent information to be leaked and (ab)used by malicious users. Kernel symbols are string representations of functions or variables that the kernel offers to kernel users (such as kernel modules and drivers). This is needed because the location of these functions/variables in memory cannot be provided in advance (this is no different from symbols used as explained in the RELRO security setting in my previous posting). By hiding these symbols from any user without sufficiently high privileges (and limit the exposure for high privileged process to well-known locations so these too can be protected by other means) it is far more difficult for malicious users to find out about available functions/variables on your system.

Finally, Kernel Heap Hardening enhances the in-kernel dynamic memory allocator with additional hardening features (double-free protection, use-after-free protection, …). It tries to ensure proper use of the allocated memory segments and protect against improper access.

From reading all this, you probably imagine why this isn’t all enabled by default. Well, many of the settings have implications on how the system behaves. Some restrict functionalities to the root user only (making it sometimes less user-friendly), some disable functionalities that are needed (like the I/O access) or are (ab)used (like the user space pointer deref which is used by many virtualization solutions) while others add some additional overhead (the more you check, the longer an action takes before it completes).

To help users select the proper settings, Gentoo Hardened tries to differentiate settings based on workstation and virtualization usage. So you get most security settings for “No Workstation, No Virtualization” and less for each of those you enable. But of course, like always, Gentoo supports custom settings too so you don’t have to follow the differentiation we suggest ;-)

Find something incorrect in the above paragraphs? Or too much sales-speak and too little explanation? Give me a shout (and prove me wrong) ;-)

Posted in Gentoo, Hardened, Security | 1 Comment

emerge-webrsync and gpg verification

Gentoo has been working on its security from very early on. One of the (many) features it supports is to allow users to validate the state of the portage tree. Ebuild signing (where developers sign the Manifest file with their key) is one of the layers offered by Gentoo, but another one is full tree signing.

When you use emerge-webrsync instead of emerge –sync, an archive containing a consistent state of the portage tree is downloaded and unpacked on your system. If you however set FEATURES="webrsync-gpg" then this tool will check the GPG signature attached to the file with the public key used by Gentoo’s infrastructure (0x239C75C4). If the archive does not contain a valid signature, then it is not used on the system.

If you want to use this, here are the steps to do so.

First, set up the location where you keep the key:

~# mkdir -p /etc/portage/gpg
~# gpg --homedir /etc/portage/gpg --keyserver subkeys.pgp.net --recv-keys 0x239C75C4
~# gpg --homedir /etc/portage/gpg --edit-key 0x239C75C4 trust

Next, edit /etc/make.conf and set the following parameters:

FEATURES="webrsync-gpg"
PORTAGE_GPG_DIR="/etc/portage/gpg"
# Disable 'emerge --sync' so emerge-webrsync has to be used
SYNC=""

With that done, you’re all set. Just run emerge-webrsync.

Happy Gentooing!

Posted in Gentoo | 2 Comments

Preliminary SELinux MCS support in Gentoo Hardened

Users tracking the hardened-dev overlay for SELinux packages will notice yet another update on the selinux-base-policy package. This time however, the change is a little more than just a policy update. With this new revision, preliminary support for Multi-Category Security (aka MCS) is added.

MCS is an update on the SELinux policy where domains and resources can be given a “category”. This is especially useful on what is called multi-tenant systems, where multiple processes (but of the same application and hence the same domain definition) are running, servicing requests of different clients (or even customers). With MCS, these different processes, although using the same domain definitions, can still be isolated. The use of categories is well accepted for virtualization hosts (where virtual guests should be run isolated from each other) and web servers, but other uses can be found easily as well.

Next to MCS, the update also supports MLS or Multi-Level Security. Like MCS, this supports multiple categories, but it also supports multiple sensitivity levels. On an MLS system, the security administrator can control how information of a certain sensitivity label “flows” through the system. Now, the MLS support within Gentoo Hardened is still very experimental so I don’t recommend it yet, unless you are willing to help us get it in a workable shape.

In order to use MCS, you need to use the POLICY_TYPES variable in /etc/make.conf (which allows Portage to build the policy type(s) you want) and the SELINUXTYPE variable in /etc/selinux/config. Whereas this previously was limited to “strict” or “targeted”, they now support “mls” and “mcs” as well. Of course, this is documented in the Gentoo Hardened SELinux handbook (currently in the hardened-doc overlay).

Now, this is still preliminary support for MCS. A small fix needs to happen on our eclass and it definitely needs lots of testing before it can be considered for production use. Also, the majority of development attention will continue in the “strict” policy type although MCS testing and support will grow.

Posted in Hardened, SELinux | Leave a comment

High level explanation on some binary executable security

One very important functionality offered by Gentoo Hardened is a specific toolchain (compiler, libraries and more) that contains patches to make the built binaries a bit more protected from certain vulnerabilities. Explaining all those in detail is too much for a simple blog post like this, but some time ago the friendly folks of the Gentoo Hardened project told be about a script called checksec.sh that displays a few of those protections on a binary.

So what can I find out of such a run? Let me show you the output on two binaries here:

~$ checksec.sh --file /opt/skype/skype
RELRO           STACK CANARY      NX            PIE                     FILE
No RELRO        Canary found      NX disabled   No PIE                  /opt/skype/skype

~$ checksec.sh --file /bin/bash
RELRO           STACK CANARY      NX            PIE                     FILE
Full RELRO      Canary found      NX enabled    PIE enabled             /bin/bash

It even comes with pretty colors (the “No RELRO” is red whereas “Full RELRO” is green). But beyond interpreting those colors (which should be obvious for the non-colorblind), what does that all mean? Well, let me try to explain them in one-paragraph entries (yes, I like such challenges ;-) Note that, if a protection is not found, then it probably means that the application was not built with this protection (the skype example, since this is a binary from Skype^WMicrosoft, versus bash which is built by the Gentoo Hardened toolchain).

RELRO stands for Relocation Read-Only, meaning that the headers in your binary, which need to be writable during startup of the application (to allow the dynamic linker to load and link stuff like shared libraries) are marked as read-only when the linker is done doing its magic (but before the application itself is launched). The difference between Partial RELRO and Full RELRO is that the Global Offset Table (and Procedure Linkage Table) which act as kind-of process-specific lookup tables for symbols (names that need to point to locations elsewhere in the application or even in loaded shared libraries) are marked read-only too in the Full RELRO. Downside of this is that lazy binding (only resolving those symbols the first time you hit them, making applications start a bit faster) is not possible anymore.

A Canary is a certain value put on the stack (memory where function local variables are also stored) and validated before that function is left again. Leaving a function means that the “previous” address (i.e. the location in the application right before the function was called) is retrieved from this stack and jumped to (well, the part right after that address – we do not want an endless loop do we?). If the canary value is not correct, then the stack might have been overwritten / corrupted (for instance by writing more stuff in the local variable than allowed – called buffer overflow) so the application is immediately stopped.

The abbreviation NX stands for non-execute or non-executable segment. It means that the application, when loaded in memory, does not allow any of its segments to be both writable and executable. The idea here is that writable memory should never be executed (as it can be manipulated) and vice versa. Having NX enabled would be good.

The last abbreviation is PIE, meaning Position Independent Executable. A No PIE application tells the loader which virtual address it should use (and keeps its memory layout quite static). Hence, attacks against this application know up-front how the virtual memory for this application is (partially) organized. Combined with in-kernel ASLR (Address Space Layout Randomization, which Gentoo’s hardened-sources of course support) PIE applications have a more diverge memory organization, making attacks that rely on the memory structure more difficult.

But hold on, the checksec.sh application also supports detection for FORTIFY_SOURCE:

~$ checksec.sh --fortify-file /opt/skype/skype
 * FORTIFY_SOURCE support available (libc)    : Yes
* Binary compiled with FORTIFY_SOURCE support: Yes

 ------ EXECUTABLE-FILE ------- . -------- LIBC --------
 FORTIFY-able library functions | Checked function names
 -------------------------------------------------------
 printf                         | __printf_chk
...
SUMMARY:

* Number of checked functions in libc                : 75
* Total number of library functions in the executable: 2468
* Number of FORTIFY-able functions in the executable : 25
* Number of checked functions in the executable      : 0
* Number of unchecked functions in the executable    : 25

In the given example, my system does support FORTIFY_SOURCE and the binary is supposedly built with this support as well, but the checks return that out of the 25 functions identified as FORTIFY-able, none of them were successfully verified as using a FORTIFY-ed library call. It goes without saying that for the /bin/bash binary, this yielded a bit more good results (12 out of 30 verified).

Again, what is FORTIFY_SOURCE? Well, when using FORTIFY_SOURCE, the compiler will try to intelligently read the code it is compiling / building. When it sees a C-library function call against a variable whose size it can deduce (like a fixed-size array – it is more intelligent than this btw) it will replace the call with a FORTIFY‘ed function call, passing on the maximum size for the variable. If this special function call notices that the variable is being overwritten beyond its boundaries, it forces the application to quit immediately. Note that not all function calls that can be fortified are fortified as that depends on the intelligence of the compiler (and if it is realistic to get the maximum size).

If you do not agree with the explanation above, please comment… and try to explain it in a single paragraph without going too detailed (i.e. do not assume people are capable of writing their own compiler just for fun).

Posted in Hardened, Security | Leave a comment

Some people on #selinux are … dolphins

A very useful resource for anyone working on or with SELinux policies is the #selinux chat channel on irc.freenode.net. People like Dominick Grift and Dan Walsh you would first think are IRC bots (being online all the time, answering questions), but I recently read that they must be … dolphins.

Yes, dolphins. Dolphins are known to not really sleep fully – only one part of their brain goes to a low-wave sleep so they’re sufficiently conscious to keep track of what is happening around them.

No seriously, thanks guys!

Posted in SELinux | Leave a comment