Tuesday, February 18, 2025

Patching Apparmor

For a little over a year, AppArmor has been broken on some distributions because of a two line bug that can be found here.

On a default Ubuntu 24.04.1 LTS installation, trying to run aa-enforce /etc/apparmor.d/* to enable apparmor profiles fails with:

Traceback (most recent call last): File "/usr/sbin/aa-enforce", line 33, 
in tool.cmd_enforce() 

File "/usr/lib/python3/dist-packages/apparmor/tools.py", line 134, 
in cmd_enforce for (program, prof_filename, output_name) in 
self.get_next_for_modechange(): 

File "/usr/lib/python3/dist-packages/apparmor/tools.py", line 97, 
in get_next_for_modechange aaui.UI_Info(_('Profile for %s 
not found, skipping') % output_name) 

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
TypeError: 'NoneType' object is not callable 
An unexpected error occurred!

The bug has been fixed in AppArmor but the patch hasn't been pushed upstream to Ubuntu yet. If we pull down the raw corrected file, we can diff and patch and get AppArmor running again. The raw fixed file can be found on Gitlab here.

Let's make a copy of our old tools.py file, just in case. We'll save it to tools.py_backup and then download the new updated version. And finally, diff, patch, and test the new file:

$ cp /usr/lib/python3/dist-packages/apparmor/tools.py /usr/lib/python3/dist-packages/apparmor/tools.py_backup
$ wget https://gitlab.com/apparmor/apparmor/-/raw/6f9e841e74f04cac78da71fd2e8af3f973af94fc/utils/apparmor/tools.py -O /tmp/tools.py
$ diff /usr/lib/python3/dist-packages/apparmor/tools.py /tmp/tools.py 
93c93
<         for (program, _, prof_filename) in self.get_next_to_profile():
---
>         for (program, _ignored, prof_filename) in self.get_next_to_profile():
165c165
<         for (program, _, prof_filename) in self.get_next_to_profile():
---
>         for (program, _ignored, prof_filename) in self.get_next_to_profile():

Nice, we can clearly see the same changes in the AppArmor github repo at commit 6f9e841e.

Diff, Patch, Repeat

If we wanted to create a patch file, we could do so by just saving the diff to an output file, like so:

$ diff -u /usr/lib/python3/dist-packages/apparmor/tools.py /tmp/tools.py > /tmp/fix.diff
$ cat /tmp/fix.diff 
--- /usr/lib/python3/dist-packages/apparmor/tools.py	2024-11-29 20:48:05.365220486 -0500
+++ /tmp/tools.py	2025-02-18 09:39:34.016987110 -0500
@@ -90,7 +90,7 @@
     def get_next_for_modechange(self):
         """common code for mode/flags changes"""
 
-        for (program, _, prof_filename) in self.get_next_to_profile():
+        for (program, _ignored, prof_filename) in self.get_next_to_profile():
             output_name = prof_filename if program is None else program
 
             if not os.path.isfile(prof_filename) or is_skippable_file(prof_filename):
@@ -162,7 +162,7 @@
     def cmd_autodep(self):
         apparmor.loadincludes()
 
-        for (program, _, prof_filename) in self.get_next_to_profile():
+        for (program, _ignored, prof_filename) in self.get_next_to_profile():
             if not program:
                 aaui.UI_Info(_('Please pass an application to generate a profile for, not a profile itself - skipping %s.') % prof_filename)
                 continue

Afterward, we could patch the file like so:

$ patch /usr/lib/python3/dist-packages/apparmor/tools.py /tmp/fix.diff

Or, simply:

$ patch < /tmp/fix.diff

Similarly, we could also reverse the patch with the -R flag and the diff file:

$ patch -R /usr/lib/python3/dist-packages/apparmor/tools.py /tmp/fix.diff

After applying the AppArmor patch, we can enable apparmor-profiles successfully again with the aa-enforce tool:

$ sudo aa-enforce /etc/apparmor.d/*
Setting /etc/apparmor.d/1password to enforce mode.
Profile for /etc/apparmor.d/abi not found, skipping
Profile for /etc/apparmor.d/abstractions not found, skipping
Profile for /etc/apparmor.d/apache2.d not found, skipping
Setting /etc/apparmor.d/balena-etcher to enforce mode.
Setting /etc/apparmor.d/bin.ping to enforce mode.
...

Sunday, February 16, 2025

The 5 Biggest Biases We Fall Victim to

This is a good post from Bruce Schneier's blog, originally published in 2011. While I can’t claim this list represents the top five cognitive biases in an empirical sense, it certainly covers a broad spectrum of the holes that tend to occur in human reasoning.

  • We tend to exaggerate spectacular and rare risks and downplay common risks.
  • The unknown is perceived to be riskier than the familiar.
  • Personified risks are perceived to be riskier than anonymous risks.
  • We underestimate risks in situations we do control, and overestimate risks in situations we don’t control.
  • We estimate the probability of something by how easy it is to bring examples to mind. (cont.)
...Newspapers repeat rare risks again and again. When something is in the news, it is, by definition, something that almost never happens. Things that are so common they stop becoming newsworthy—like car accidents—are what you need to worry about.

"The 5 Biggest Biases We Fall Victim to"

Friday, February 07, 2025

Your Life in Weeks

This morning I saw a post on twitter that said:

The tragedy about waiting 6 months for something is that there aren't many "6 months" in a human life to wait.

This was in the context of a discussion about various services and their relative speeds, e.g. Amazon delivery versus health care or city planning. Amazon might be able to deliver a thing tomorrow. Fixing a road, acquiring a city permit, or getting a doctor's appointment might take several months.

But the general point is true in the long-view of life in its entirety -- the clock is always there, ticking. Time is essentially the ultimate currency. Lost or stolen time can never be returned or recovered.

It reminded me of this post from Wait but Why -- an illustration of the average human lifespan. This hit me hard when I first saw it. Life feels long until you see it laid out in weeks: https://waitbutwhy.com/2014/05/life-weeks.html

Monday, January 20, 2025

The Old New World

Lately I've been thinking about the differences in people growing up today versus the lives of past generations. When I recall my own childhood, I think about how different the world seemed back then. By the time I was seven, my father had taught me how to use a telescope, ride a bicycle, build ramps, play baseball, rollerblade, play hockey, and how to play the guitar, as well as how to build instruments. My father would also read me history—though, at the time, I wasn't as enthusiastic about that as I was about riding bicycles or playing sports.

I remember zooming around the neighborhood with friends as the sun fell beneath the horizon and orange streetlights lit up—just as my mother would holler that dinner was ready. My mother would work during the day, and my father at night. And they both provided me with knowledge and resources for survival, instilling in me many good traits—and a moral compass.

However, when I was younger and more naive, I thought my parents—especially my father—were tough on me. But now that I am older, I see only how lucky and fortunate I was.

But also I wonder if future generations will be less adventurous, and less active, due to new "norms," like video games and digital content creation/consumption. Will future kids know what it's like to run around their neighborhoods in a high-trust society underneath orange streetlights? Will they, as I did, learn to play sports, or have regimens of physical activity, or be taught how things work by a generation of skillful people that came before them? Will future families venerate strength and beauty? Has that world been destroyed? If so, will it exist again some day? If that old world has only faded, can it ever be rekindled?

Monday, December 30, 2024

Prevent Chrome's Translation Feature from Reformatting Code Blocks

Chrome Browser annoyingly reformats code blocks occasionally when using the translate feature. For example, if you translate a Chinese web page to English—if there are code blocks, it may also parse and reformat them, making them harder to read. Here's a workaround via Chrome DevTools Console. Run this before translating a web page:

// browser console hack to prevent chrome from mucking  
// with code blocks whenever a page is translated, 
// e.g. translating a chinese page to english

document.querySelectorAll('pre, code').forEach(block => {
  block.style.whiteSpace = 'pre-wrap';
  block.setAttribute('translate', 'no');
});

Monday, December 16, 2024

Early Timekeeping

Why are there sixty seconds in a minute, sixty minutes in an hour, yet twenty-four hours in a day? The answer is because modern timekeeping derives from the base-60 number system.

It is believed that Sumerians of Mesopotamia used their phalanges to count. They counted increments of 12 with one hand's four fingers, each of which has three bones, and tracked them with the other hand's five fingers: 12, 24, 36, 48, 60.

Early civilization calendars were often lunisolar, based on the phases of the moon—roughly aware of the sun's yearly 365-day orbit. Though they were somewhat imprecise, many resembled the 12-month calendar we know today. Ancient calendars, however, would often have extra days or months periodically added for alignment purposes.

The Sumerians had no tradition for referring to the length of time we call a "week," nor did they identify months. They simply observed months and years. Later, the Babylonians would put forth the notion of the "week," as well as move to use a solar, rather than lunisolar, calendar.

A history of calendars: https://en.wikipedia.org/wiki/History_of_calendars

God as Atheist

In Orthodoxy, G.K. Chesterton turns familiar ideas upside down and urges us to see truth in paradox.

Chesterton says that, for example, artists like and enjoy their own limitations, precisely because they are defined by those limitations. Constraints themselves are a kind of source from which creativity springs.

But one of the most interesting sections of Orthodoxy is when Chesterton begins to remark more directly about religion.

Chesterton notes that Christianity is one of the only religions in which the idea of "God" is not an omnipotent force—on the contrary, God is represented in a trinity—including one branch in which God himself is human in the form of Christ. He describes the crucifixion of Christ, pointing out that Christianity is paradoxically one of the only religions in which God himself briefly becomes an atheist.

All moral reform must start in the active not the passive will.

Here again we reach the same substantial conclusion. In so far as we desire the definite reconstructions and the dangerous revolutions which have distinguished European civilisation, we shall not discourage the thought of possible ruin; we shall rather encourage it. If we want, like the Eastern saints, merely to contemplate how right things are, of course we shall only say that they must go right. But if we particularly want to make them go right, we must insist that they may go wrong.

Lastly, this truth is yet again true in the case of the common modern attempts to diminish or to explain away the divinity of Christ. The thing may be true or not; that I shall deal with before I end. But if the divinity is true it is certainly terribly revolutionary. That a good man may have his back to the wall is no more than we knew already; but that God could have his back to the wall is a boast for all insurgents for ever. Christianity is the only religion on earth that has felt that omnipotence made God incomplete. Christianity alone has felt that God, to be wholly God, must have been a rebel as well as a king. Alone of all creeds, Christianity has added courage to the virtues of the Creator. For the only courage worth calling courage must necessarily mean that the soul passes a breaking point — and does not break. In this indeed I approach a matter more dark and awful than it is easy to discuss; and I apologise in advance if any of my phrases fall wrong or seem irreverent touching a matter which the greatest saints and thinkers have justly feared to approach. But in that terrific tale of the Passion there is a distinct emotional suggestion that the author of all things (in some unthinkable way) went not only through agony, but through doubt. It is written, "Thou shalt not tempt the Lord thy God." No; but the Lord thy God may tempt Himself; and it seems as if this was what happened in Gcthsemane. In a garden Satan tempted man: and in a garden God tempted God. He passed in some superhuman manner through our human horror of pessimism. When the world shook and the sun was wiped out of heaven, it was not at the crucifixion, but at the cry from the cross: the cry which confessed that God was forsaken of God. And now let the revolutionists choose a creed from all the creeds and a god from all the gods of the world, carefully weighing all the gods of inevitable recurrence and of unalterable power. They will not find another god who has himself been in revolt. Nay, (the matter grows too difficult for human speech) but let the atheists themselves choose a god. They will find only one divinity who ever uttered their isolation; only one religion in which God seemed for an instant to be an atheist.

Using Python To Access archive.today, July 2025

It seems like a lot of the previous software wrappers to interact with archive.today (and archive.is, archive.ph, etc) via the command-line ...