Installing SELinux

This article provides notes on how to install Security Enhanced Linux (SELinux) on an Ubuntu 22.04 Linux system. These notes are based on my experience doing this installation and some of the issues I encountered while doing so. There are other resources online that describe this procedure, but the ones I encountered are either old, incomplete, give bad advice, or are just plain wrong. Although I don’t have all the answers myself, I hope to maintain this article by editing it in the future when I learn more.

Introduction

SELinux is a mandatory access control (MAC) system for Linux. This means that access to resources, such as files, are controlled by the system administrator rather than by the resource owner as is the case in a discretionary access control (DAC) system. SELinux is implemented as a Linux Security Module (LSM), which is a standard way to add additional security features to the Linux kernel. However, SELinux is more than just an LSM. To be a practical system, it must also provide modified versions of some system tools, such as ‘ls’ and ‘ps’, as well as SELinux-specific tools that know how to interact with the SELinux-enabled kernel.

It is important to understand that SELinux acts in addition to the normal DAC system available in traditional Linux. Access to a file is granted only if both systems agree that it should be granted. Everything you already know about the way file permissions and access control lists work still applies after SELinux is installed.

Ubuntu Linux comes with a MAC system pre-installed and pre-configured called AppArmor. It is also implemented as an LSM. It is my understanding that LSMs are “stackable” in the sense that multiple LSMs can be in use at the same time. In fact, normal Linux capabilities are implemented via an LSM which runs alongside AppArmor (or SELinux). However, I have seen suggestions elsewhere online that say AppArmor is incompatible with SELinux and will conflict with it. I wonder about the truth of that, but I agree that using two complex MAC systems at once is a bad idea even if they could technically coexist. Thus, before installing SELinux you will want to disable AppArmor as I describe in the next section.

It should be mentioned that some Linux distributions come with SELinux pre-installed and pre-configured instead of AppArmor. Other distributions, such as Ubuntu, have decided to use AppArmor instead. This means installing SELinux on a Ubuntu system is swimming against the current to some extent. You may experience more issues and quirks than you might with a different distribution that is designed around SELinux. Running SELinux on Ubuntu is not “official” in the way running AppArmor is.

One quirk is related to snap. Information I’ve found online suggests that snap has a dependency on AppArmor. This surprises me; I don’t understand why a packaging system would depend on a MAC system. I do understand that snaps might come with AppArmor rules that govern the operation of the installed software, but it seems to me that the functional behavior of a snap should not require the presence (or absence) of a certain MAC solution. I may not understand snaps very well.

Since Ubuntu 22.04 provides some software packages as snaps, it is possible, perhaps likely, that those packages won’t work once AppArmor is disabled. For example, Firefox is provided as a snap (by default), and it does not work after AppArmor is disabled. Also, it is no longer possible to remove snaps after AppArmor is disabled because the snap infrastructure does not work sufficiently well at that point. So, before embarking on an installation of SELinux on your Ubuntu system, you should review what snaps you are using and verify that you can live without them. If you want to remove a snap, be sure to do so before you begin the process described in the next section. To list your installed snaps, do:

$ snap list

The command ‘snap remove’ can be used to remove snaps if you choose to do so.

Keep in mind that managing SELinux is not a trivial activity. SELinux is best suited to systems where extra security is essential, such as public-facing servers. It is not a good fit for a system that is intended to be used as a general-purpose workstation. So, while installing SELinux may make sense for your institutional web server or database server, you might not want to install it on your day-to-day desktop. The kind of systems for which SELinux makes sense don’t normally have many snaps installed anyway, so this issue may not be significant in practice.

If you are still interested in installing SELinux on your Ubuntu 22.04 system, I will describe the specific procedure for doing so in the next section.

Installing SELinux

The best description I’ve found for this process is on the Linode site. The information below elaborates on what that site describes.

The first step to install SELinux on Ubuntu 22.04 is to stop and disable AppArmor as described in the introduction above.

# systemctl stop apparmor
# systemctl disable apparmor

The first command stops the AppArmor temporarily. The second command disables AppArmor from restarting with the system reboots. It is not necessary to remove AppArmor. In fact, to facilitate returning the system to its original state, I recommend leaving the AppArmor files in place.

To install SELinux itself do the following:

# apt install policycoreutils selinux-basics selinux-utils -y
# selinux-activate

The -y option tells apt to take “yes” as your response to all relevant yes/no questions. If you prefer a more interactive installation experience, you can leave the -y out. You should see a message about SELinux being activated and suggesting that you reboot. However, before rebooting it is advisable to review the configuration first. Use this command to check the mode in which SELinux is operating:

$ getenforce

Notice that you do not need to be the superuser to run this command. There are three outputs: “Disabled” means that SELinux is installed but not doing anything. “Permissive” means that SELinux is checking all operations against the current policy but not enforcing any of the restrictions defined by that policy. Violations are logged in the system log file. “Enforcing” means that SELinux is enforcing the restrictions defined by the policy. After you install the SELinux packages and activate SELinux as above, the mode should be “Disabled.”

Now check the file /etc/selinux/config. This is a plain text file that contains SELinux’s basic configuration settings. Verify that the line SELINUX=permissive is in the file. This the mode SELinux will come up in at the next reboot. It is essential that you start SELinux in permissive mode! The default policy will cause many violations. If you enforce the default policy, your system may be unbootable because of those violations.

The procedure is to run your system for a while in permissive mode and monitor the policy violations in the system log file. Work through those violations by either reconfiguring the software that is causing them or by modifying the policy. Only when the policy violations are minimal or non-existent should you consider changing the mode to enforcing.

Once you are convinced that the configuration is for permissive mode, reboot your system. I recommend you do this with access to the console rather than rebooting remotely. The first boot after activating SELinux takes a long time because the system must add labels to all objects in the file system. Depending on how many files and folders you have on your disks, the time to do this can be considerable. In my case it took about 20 minutes. If there is a problem with this process, or any unusual messages produced by it, you will want to be at the console to see them.

Once the system has fully rebooted again run the getenforce command to verify that the mode is now “Permissive.” Inspect the file /var/log/syslog for policy violation messages. You will see many.

Next Steps

Your system is now running SELinux, but SELinux is providing no security since it is in permissive mode. In fact, your system is less secure than it was with AppArmor running. You will want to fix this. Here is an outline of what needs to be done next. I may write more details in a later blog post (to which I will link) or by editing this post.

  1. Install a more suitable default policy. The default policy installed with SELinux may not be well matched to the way you are using your system. Since SELinux policies are complex, you may be able to download a different policy that would be more suitable for your machine. Starting with such a policy can minimize the number of policy violations you must clean up by hand. Of course, be careful when downloading a security policy from the Internet. Be sure to review it before you try to use it.
  2. Edit the policy or modify software configurations (or change your working procedures) to remove all policy violations. The idea is to tune the SELinux policy to match the normal way you use your system. If you don’t do this then when you turn on enforcing mode, some things will break. This process may take days, weeks, or even months.
  3. Enable enforcing mode. Once you are ready, change the SELinux configuration file to specify enforcing mode and reboot. Assuming you did your due diligence in step #2 above, the system should restart and work normally.
  4. Monitor the system. You will have to fine-tune your policy in an ongoing way. It is likely that no matter how much time you spent on step #2 above, there will be things you forget to handle. Also, of course, if someone attacks your system you may find policy violations that reflect attempts to access resources without authorization.
  5. Lock down the system. It is theoretically possible to write an SELinux policy so that nobody, not even root, can edit the policy. This prevents someone who does get root access remotely from making the policy more permissive, or even setting SELinux back to permissive mode altogether. However, this also means that when you want to legitimately modify the policy you will need to reboot the system in permissive mode by using appropriate command line arguments to the kernel at boot time (i. e, in grub before the kernel loads). Doing so requires physical access to the system’s console, so this isn’t a change to make lightly.

This summarizes how to install SELinux on Ubuntu 22.04. This article is subject to change and extension as I learn more myself. I hope to provide some details about each of the “next steps” that I outline above.

Enjoy!

A Collection of Notes

Finally, I have decided what I would like to do with this blog. I will use it to store notes on how to do various (technical) things. Often, I need to work out the details of how to install and configure a package, how to make use of some software library, or how to implement some tricky algorithm. Like many people, I often rely on resources I find on the web to help me. Some of those resources are excellent, but some are incomplete, old, misleading, or have other problems. I’m thinking I’d like to use this blog to give back to the Internet community by sharing interesting tidbits that I have discovered, leaving them here for others to find.

For this idea to work, I will need to include blocks of fixed-width text in these entries for showing commands, program text, and similar things. I may also need to include images (diagrams, for example). Let me see if I can figure out how to do that using the editor WordPress provides…

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
    printf("Hello, World!\n");
    return EXIT_SUCCESS;
}

How does that look? It’s not terrible. I feel like the lines might look better if they were a bit closer together, but I assume that’s under the control of a style that I can adjust later, if necessary.

Here is a link to the web site I maintain for my classes at Vermont Technical College. It’s good to see that linking is easy (of course!).

New Section

It is, of course important to create lists when describing procedures:

  1. Get ready. You can’t do anything useful without preparing yourself first.
  2. Do the thing. Once you are ready, go ahead and do it.
  3. Clean up the mess. There is always a mess afterward that needs to be cleaned up.

That sums up the procedure that must be followed for most things. Nothing more needs to be said. All future posts will only provide elaborations on, and examples of, the universal procedure above.

Okay, I get the general idea. I see there are many other editing features that I can use. I think I can work with this.

Restart?

It has been 12 years since I last posted anything here. I think the time has come (probably long overdue) for me to restart this blog in some useful way. However, I’m not sure I want to follow the original vision I had for this blog when I started it. Much has happened since then in my life, and my goals and perspectives have changed. Or have they? My first task needs to be re-imagining this blog in light of my current personal and professional situation.

In recent times I have been working extensively with Ada and SPARK, so that is an obvious direction to take this space. However, it is also true that my retirement approaches (a few more years, admittedly), so creating something that I can continue when I retire, such as talking about my various software projects, is another possibility. Of course these ideas are not mutually exclusive, nor do they exclude still other ideas. In any case, the blog has been “dead” for years. Consider it restarted, and watch this space over the coming months to see what develops.

Exception Specifications

Both C++ and Java (and other programming languages as well) support a notion of exception specifications. The design and even the desirability of these specifications is controversial. In C++, for example, the exception specifications are enforced at run time; if a function throws an unexpected exception the running program is (by default) aborted. In Java the exception specifications are enforced statically. If a method tries to throw an unexpected exception the program won’t compile. Which approach is better?

Exceptions are a dynamic process. The precise exceptions thrown by a program and where they are handled depend on the inputs given to it and on the execution path taken by the program as it runs. One might reasonably wonder if all possible exceptions that a program might throw are handled somewhere. Can this even be determined statically? My guess is that the question is undecidable in the general case. I don’t have a proof of this, but I’d be surprised if it was otherwise. Thus any static analysis must necessarily be either unsound or incomplete or both. In the case of exception specifications this means that either the analysis misses some exceptions that might be thrown and thus says all exceptions are handled when they are not (unsound), or the analysis forces the programmer to handle exceptions that in fact can never be thrown (incomplete).

Many exceptions have the potential to arise very often. For example in Java the null pointer dereferencing exception could potentially arise whenever an object or array is accessed. Requiring this exception to be part of an exception specification would essentially mean that every method would need to be decorated with that exception (and then what would that really tell you?). To avoid this Java’s exception specifications are unsound; certain exceptions, the so called “unchecked” exceptions, do not need to be covered by exception specifications. However, this means that the static analysis done by the compiler doesn’t really answer the question you’d like answered: are all possible exceptions handled in some way? Yet despite that, Java’s handling of exception specifications is also incomplete; among checked exceptions it is still possible that the compiler will force you to handle an exception that, under your specific conditions, can’t occur.

C++ checks exceptions specifications dynamically. This has the advantage of being precise; only those exceptions that actually do violate the specifications are reported. However, this leaves open the problem of what should be done when such a violation is detected. The program is already running at that point so the way in which this error should best be handled is likely to be application specific. Aborting the program outright might be reasonable in some cases, but probably not in most cases. C++ allows the programmer to translate unexpected exceptions into expected ones (using unexpected handlers) but this has the disadvantage of throwing away information about the original exception (although one could imagine an unexpected handler that logs the original exception in some way before translating it).

Yet there are issues with exception specifications that transend the static vs dynamic question. For example an exception thrown in a call back function that propagates through a third party module and is eventually handled by the client of that module should be perfectly well behaved. Yet the exception specifications in the third party module can’t possibly know about the client’s exceptions. There are also questions regarding the handling of exception specifications in generics or templates, etc. Many issues with exception specifications have been described with proponents on both sides of every argument. One is left with the distinct impression that the community just doesn’t know right now how to best handle exception specifications.

To summarize, static checking of exception specifications is unsound and dynamic checking leaves open the problem of how to handle violations. For these reasons, along with other questions about them, I suggest that exception specifications, as we currently understand them, are a bad idea. I am glad that Ada, my favorite language, does not have them. I would encourage the Ada community to be very careful about incorporating them into a future version of the language. I’m not saying that exception specifications can’t be defined in a reasonable and useful way. I’m only saying that doing so is trickier than it at first appears and that neither Java nor C++ got it right.

Project Wheel

Not long ago the Visual Studio installation on my main laptop decided to not work. Specifically, as soon as I opened any project Visual Studio closed immediately without any messages of any kind. The problem turned out to be related to the VMware plug-in for Visual Studio.

Any heavy computer user is going to encounter issues like this from time to time. That’s just life in this field. Still, when it happens to me I tend to get philosophical. I wonder if computer systems have become too complicated for their own good. Certainly I personally do not need all of the features and capibilities that modern software packages provide. I didn’t even know VMware had a Visual Studio plug-in until it started acting up on me. When complex software packages begin to misbehave because of interactions between components I don’t care about… something has to be done. But what?

I long for the days of simple software. I want software that only does what I need and not one thing more. Of course when I need my software to do something new, I’d like that new feature to become available. How could that happen? There is only one way I can see to get software like that: write it myself.

Thus I introduce “Project Wheel.” The goal of Project Wheel is to build a system composed entirely of software I wrote myself. Such a system would be small and simple (out of necessity), and also extremely customized to suite my needs. In addition I would, in theory, understand how it all works… and be in a position to personally fix anything that is broken.

Of course this idea is utterly nuts. Even if I worked 24/7 for the rest of my life I would not be able to single handedly buid a usable system from scratch. Yet even if the goal is unattainable the philosophy is, perhaps, still worthwhile. It is a philosophy of simplicity and self-reliance. Software should be functional, to the point, and tailored to the individual… not loaded with useless glitz that might (or might not) be interesting to someone somewhere.

Yet if Wheel is to have any practical feasibility at all, some concessions will be necessary. For example, I think one reasonable compromise would be to use software built by a team of which you are a member. Thus a follower of Wheel could use traditional open source packages provided he or she is actively participating in the development of those packages.

For example, I’m involved in the development of Open Watcom. Thus I could be fairly true to the Wheel philosophy if I used Open Watcom as the compiler for all my programs. It’s true that I don’t understand how all of Open Watcom works. However, I could in principle come to understand it because it is open source and, what’s more, I’m already engaged with that project and working on it.

Obviously it isn’t feasible to build an entire, modern system from custom made software. Yet I wonder how far one can really go with this idea. Years ago I wrote a simple text editor of my own. Maybe it’s time to clean up that source, compile it with Open Watcom, and then use it to start cranking out software. Yes, maybe it’s time to reinvent the wheel.

Discovering OpenSolaris

I’m back! I’ve decided to give blogging another try. Maybe I’ll find my blogging groove this time around. Or maybe I just like playing around with WordPress!

I was recently introduced to OpenSolaris, the open source version of the Solaris operating system. I downloaded the base system from the OpenSolaris web site and installed it into a VMware Workstation virtual machine. The installation was easy. However, the Solaris VMware Tools that come with my version of VMware Workstation (v6.0.3) do not seem happy with OpenSolaris. I have not yet looked into why. Fortunately the system seems to run adequately without VMware Tools.

OpenSolaris installs with a GNOME desktop and so visually it looks a lot like many Linux systems. It doesn’t take much poking around, though, to start seeing differences. For one thing, the base system lacks a lot of packages that I consider essential… such as a C compiler. I’m sure many additional packages can be readily obtained (for example, through the package manager!) although I haven’t looked into doing that yet.

In fact I haven’t spent much time so far exploring the system, and so I can’t say much about it right now. My first impressions are favorable, however. It seems clean and well behaved. I may write about OpenSolaris again in the future once I’ve gained more experience with it.

Indefinite Hold

I’ve had this blog for about eight months and yet I’ve only posted a few entries in it. Honestly I don’t have all that much to say, and I don’t want to talk just to hear myself talk. Instead of spending time maintaining this blog I find that I’d rather spend time working on one of my many projects. So I’m officially putting this blog on indefinite hold. I may return to it someday when I have in mind a clearer purpose for it. I may never return.

The point of blogging has always been unclear to me. I can see the value of it as a way to support or promote an open source project (for example). Such blogs are well focused and often contain interesting and useful information for the users of the project. However, a blog that is nothing more than technically rambling does seem rather useless.

Email + IM?

It is common to find single applications that integrate several services that could have sensibly been provided with separate applications instead. How much integration is smart is, of course, a matter of opinion. I think integration makes sense if the things being integrated are closely related and can reasonably share application features. For example, Thunderbird supports both email and NNTP newsgroup access. This makes sense because both mail and newsgroups serve a similar purpose. Also both systems can benefit from a unified address book and common message folders. In addition, both systems support similar kinds of message content.

What about instant messaging? Many people today use IM as a major form of interpersonal communication. In some communities it is replacing email as the communication method of choice. IM systems such as Jabber even support asychronous messages; the recipient of a message need not be logged in at the time the message is sent. One can easily see the sense in using an IM sytem for informal conversation and traditional email only for longer, more formal, and more complex documents.

Given this observation, does it make sense to build an integerated email+IM client? Again both systems could benefit from a unified handling of contacts, and it might be nice to store chat session logs in folders alongside email messages. Indeed, Google appears to be headed in this very direction with Gmail and Google Talk. However, I do not know of any desktop email+IM application. Is there one? Should there be one?

Notepad++

I have a thing for editors it seems. Over the years I’ve used quite a variety of different ones. I’ve even written an editor of my own. As I mentioned in an earlier post, I’ve recently taken to using jEdit for my day to day editing needs. However any editor as powerful as jEdit is also a bit heavy for some applications. It’s nice to have an editor on hand that installs easily, loads quickly, and yet is still powerful enough for “real” editing when necessary. One such editor is Notepad++.

Notepad++ has become a popular tool among students at Vermont Technical College where I teach. Students like it because it is easy to use and yet modern enough to be a comfortable editing environment for programming assignments, web pages, and most anything else. Indeed, Notepad++ is surprisingly feature rich for such a small download. It supports syntax highlighting for a wide collection of programming languages, macros, various Unicode encodings, and even a plug-in architecture with a significant number of plug-ins available on the Notepad++ site. The fact that it is open source is an added bonus.

I tend to use Notepad++ when I want to take a quick look at an arbitrary text file, treating the program as a kind of file viewer with editing features. It loads faster than jEdit so it is a good choice for quick and dirty editing when jEdit isn’t already running. Also since Notepad++ is installed on all the lab machines at Vermont Technical College I know I can use it anywhere in our labs without complication. Many of my students use Notepad++ for all their editing needs.

If you are looking for a small, light editor that is also worth using, consider Notepad++.

Is jEdit a Worthy Replacement for Emacs?

I am a long time Emacs user. Yet although I’m comfortable with the editor, I have never really achieved “power user” status with it. I dabbled with some macros and I fiddled around with my .emacs file, but I never got around to creating any non-trivial code to extend the editor in a useful way. Also as much as I respect Emacs, I’ve grown somewhat tired of its old fashion and rather quirky interface. Thus I started looking around for a more modern editor that, like Emacs, would be powerful, extensible, and free.

I found jEdit.

I like the fact that jEdit is cross platform. I use both Windows and Linux systems extensively and, like Emacs, I can run jEdit quite nicely in both of those environments. I also like the fact that jEdit can be extended with Java plug-ins and Beanshell macros. jEdit has plenty of features, particularly with the help of a rich collection of third party plug-ins, and it sports a much more modern interface than, well… Emacs.

My only complaints about jEdit are: 1) The interface is ugly, and 2) The quality of the third party plug-ins is quite variable. Some of the available plug-ins are very nice and work wonderfully. Some are rather rinky dink. Thus one’s experience of using jEdit depends heavily on which plug-ins are involved.

Overall, however, I find myself liking jEdit more all the time. Lately I keep jEdit running constantly on my desktop and use it for all my text editing needs. In the past I ran Emacs that way, but lately Emacs has been relegated to occasional, specialized use. Now I feel like I’m ready to take jEdit to the next level and begin creating some macros and plug-ins for the complex editing tasks that I had always planned to do with Emacs some day.

Is jEdit a worthy replacement for Emacs? Maybe so.