It s been about a month since I wrapped up my Outreachy internship, but my journey with Debian is far from over. I planned to keep contributing and exploring the community, and these past few weeks have been busy
For the openQA project, we decided to explore how accurate local language installations are and see if we can improve the translations. While exploring this, I started working on automating a test for a specific bug report: Debian Bug #1111214
This is a test I had started by writing a detailed description of the installation process to confirm that selecting the Spanish_panama locale works accurately. I spent time studying previous language installation tests, and I learned that I needed to add a specific tag (LANGUAGE-) to the needles (visual test markers).
Since the installation wasn t in English anymore, taking the correct screenshots and defining the areas took quite some time. I used the following command on the CLI to run the test:
openqa-cli api -X POST isos ISO=debian-live-testing-amd64-gnome.iso DISTRI=debian-live VERSION=forky FLAVOR=gnome LANGUAGE=spanish_panama ARCH=x86_64 BUILD=1311 CHECKSUM=unknown
While working on this, I got stuck at the complete_installation step. Because the keyboard layout had changed to Spanish, the commands required to confirm a successful install weren t working as expected. Specifically, we had an issue typing the greater than sign (>).
My mentor, Roland Clobus, worked on a clever maneuver for the keys (AltGr-Shift-X), which was actually submitted upstream to openSUSE.
In this step, I also had to confirm that the locale was correctly set to LANG= es_PA.UTF-8 . I had to dig into the scripts and Linux commands to make this work. It was a bit intimidating at first, but it turned out to be a great learning experience. You can follow my progress on this Merge Request here. I m currently debugging a small issue where the home key seems to click twice in the final step, and after that, the test would be complete
.
Beyond the code, I ve been getting more involved in the social side of Debian:
On June 19 and 20, I will cycle a little over 100 miles from downtown
Chicago and its wonderful Millenium Park to New Buffalo, Michigan, as
part of the Tour de Shore
2026. The ride passes through northwest Indiana and the extended Indiana Dunes National
Park ending the next morning in the southwestern Michigan town of
New Buffalo. I rode Tour de Shore once before in 2024 and had a
generally wonderful time (even considering some soreness after a century
of miles over 1 1/2 days).
Tour de Shore is riding
in support of Maywood Fine Arts
Center, a local arts and sports center in Maywood,
Illinois, a suburb one over from where I live and hence just a few
good miles west of downtown. Maywood,
Illinois is home to legends such as the late John Prine as well
as several NBA players such as player and coach Doc Rivers.
But Maywood,
Illinois is also little less well off than other western suburbs.
The Maywood Fine Arts Center
is simply legendary is what they do for this community (and surrounding
communities), and especially the youth support. They can use a dollar a
two. Their
story about Tour de Shore is worth a read too for background and
motivation.
I have bootstrapped my
donation page page with a dollar for each mile to be cycled. It
would be simply terrific if you could join me. A nickel, a dime, or a
quarter per mile cycled would help. Multiples of that help too: More is
of course still always better.
Anything you can afford will go a long way towards a worthy goal in a
community that could use the help.
Of and if you are local to the area, I believe you can still register for Tour de
Shore 2026. So see you out there in June? And if not, maybe help
with a dollar or two?
This post by Dirk Eddelbuettel originated on his Thinking inside the box blog.
dnf swap -y libcurl-minimal libcurl-full
dnf swap -y curl-minimal curl-full
curl --http3-only https://example.com
(HTTP/3 is only enabled in the curl -full builds)
Or, if you would like to try it out in a container:
podman run amazonlinux:2023 /bin/sh -c 'dnf upgrade -y --releasever=latest && dnf swap -y libcurl-minimal libcurl-full && dnf swap -y curl-minimal curl-full && curl --http3-only https://example.com'
For a list of test endpoints, you can refer to
https://bagder.github.io/HTTP3-test/
--http3 or --http3-only.
| Series: | Sector General #7 |
| Publisher: | Orb |
| Copyright: | 1987 |
| Printing: | May 2003 |
| ISBN: | 0-7653-0663-8 |
| Format: | Trade paperback |
| Pages: | 252 |
dumpdata loaddata workflows are designed
to move the table definitions and a small amount of data. In our case, even
after just 15% of our lists moved, our sqlite database was about 30GB.
I considered some of the hacks to manage memory and try to run this via django,
but eventually decided that pgloader was a more robust
option. This option also allowed me to more easily test things out on a copy of
our sqlite database (made while mailman was turned off). This way I could
migrate and re-migrate the sqlite database over and over without impacting our
live installation until I was satisfied it was all working.
My first decision was to opt out of pgloader s schema creation. I used django s
schema creation tool by:
mailman-web migratemailman-web migrate --database new. But,
during the migration, I caught django querying the sqlite database for some
migrations that required referencing existing fields (specifically hyperkitty s
0003_thread_starting_email). I didn t want any of these steps to touch the
live database so I opted for the cleaner approach.
Once I had a clean postgres schema, I dumped it so I could easily return to
this spot.
Next I started working on our pgloader load file. After a lot of trial and
error, I ended with:
LOAD DATABASE
FROM sqlite:///var/lib/mailman3/sqlite-postgres-migration/mailman3web.clean.backup.db
INTO postgresql://mailmanweb:xxxxxxxxxxx@localhost:5432/mailmanweb
WITH data only,
reset sequences,
include no drop,
disable triggers,
create no tables,
batch size = 5MB,
batch rows = 500,
prefetch rows = 50,
workers = 2,
concurrency = 1
SET work_mem to '64MB',
maintenance_work_mem to '512MB'
CAST type datetime to timestamptz drop default drop not null,
type date to date drop default drop not null,
type int when (= precision 1) to boolean using tinyint-to-boolean,
type text to varchar using remove-null-characters;
TRUNCATE TABLE django_migrations CASCADE;
TRUNCATE TABLE django_content_type CASCADE;
TRUNCATE TABLE auth_permission CASCADE;
TRUNCATE TABLE django_site CASCADE;
ALTER TABLE hyperkitty_attachment ALTER COLUMN name TYPE text
pgloader runs, we still get a lot of warnings from pgloader, which wants
to cast columns differently than django does. These are harmless (I was able to
import the data without a problem).
And there are still a lot of warnings along the lines of:
2026-03-30T14:08:01.691990Z WARNING PostgreSQL warning: constraint hyperkitty_vote_email_id_73a50f4d_fk_hyperkitty_email_id of relation hyperkitty_vote does not exist, skippingThese are harmless as well. They appear because
disable triggers disables
foreign key constraints. Without it, we wouldn t be able to load tables that
require values in tables that have not yet been populated.
After all the tweaking, the import of our 30GB sqlite database took about 40
minutes.
reset sequences from pgloader should take care of this, but just in case:
mailman-web sqlsequencereset hyperkitty mailman_django auth mailman-web dbshell
ANALYZE VERBOSE;
| Series: | Magic of the Lost #3 |
| Publisher: | Orbit |
| Copyright: | September 2025 |
| ISBN: | 0-316-54286-5 |
| Format: | Kindle |
| Pages: | 575 |
/etc/apt/sources.list.d/r-samueloph-nvidia-ai.sources, run sudo apt update and install the packages, you might need to disable Secure Boot.
.sources file you need, create the
file /etc/apt/sources.list.d/r-samueloph-nvidia-ai.sources with the sources for your release.
Run sudo apt update and install the packages you need, if you already have a
previous version installed, sudo apt upgrade --update would update them.
If there are no upgrades, meaning you don't have a previous version installed,
then you need to explicitly install them.
sudo apt install nvidia-open-kernel-dkms nvidia-driver
If you run into issues in Debian Stable, consider using the Linux kernel package
from the backports repository, if you need an up-to-date NVIDIA driver, you
likely should also be running the backports kernel package (if you can't
upgrade to Debian Testing).
I was reading a post on Alex Chan's
website1 that referenced the concept of
digital gardens,
a concept/analogy for organising information which dates back to the 90s.
This old concept is getting new traction today by contrasting the approach
with "endless stream" as used and abused by social media, but also how blogs
are typically presented.
This site, my homepage, has a blog, and that's the bit that most people who
interact with the site will experience. Partly, because it's the bit that gets
syndicated out: via feeds; on Planet
Debian and downstream from it; once upon a time on
Twitter; nowadays on the Fediverse.
However there's more to my homepage than that. The rest of it may be of little
interest to anyone beside me, but it's useful to me, at least. So I may switch
focus a little bit from mainly writing blog posts, and tend to the rest of the
garden a bit more.
Some recent seeding and pruning:
Recently my guest status at Newcastle University came up for renewal, so I
wrote down my goals in the Historic Computing Committee for the next year or
so, and put them here: nuhcc. I've also been pondering what I'm up to in
Debian at the moment, so took some time to add my current projects to
that page.
| Series: | Long Price Quartet #1 |
| Publisher: | Tor |
| Copyright: | March 2006 |
| ISBN: | 0-7653-1340-5 |
| Format: | Hardcover |
| Pages: | 331 |
This needs to be clear: systemd is under attack by a trolling campaign orchestrated by fascist elements. Nobody is forced to like or use systemd, but anybody who wants to pick a side should know the facts.
Recently, the free software Nazi bar crowd styling themselves as "concerned citizens" has tried to start a moral panic by saying that systemd is implementing age verification checks or that somehow it will require providing personally identifiable information.
This is a lie: the facts are simply that the systemd users database has gained an optional "date of birth" field, which the desktop environments may use or not as they deem appropriate. Of course there is no "identity verification" or requirements to provide any data, which in any case would not be shared beyond authorized local applications.
While the multiple recent bills proposing that general purpose operating systems implement age verification mechanisms are often concerning, both from a social and technical point of view, this is not the topic being discussed here. They are often suboptimal, but for a long time I have been opposing attempts to implement parental control at the network level and argued that it should be managed locally, by parents on their own machines: I cannot see why I should outright reject an attempt to implement the infrastructure to do that.
If we want to keep age-appropriate controls out of the hands of centralized authorities, the alternative is giving families the means to manage it themselves: this is what this field enables. Whether desktop environments use it for parental controls, for birthday reminders, or for nothing at all, is their users' decision.
By the way, the original UNIX users database has allowed storing PII in the GECOS field since it was invented in the '70s. Similar fields are also specified by many popular LDAP schemes: adding such an optional field is consistent with the UNIX tradition.
And while we are at it, let's also refute the other smear campaign started by the same people: the systemd project is not accepting "AI slop". What happened is that a documentation file for the benefit of coding agents was added to the repository. To be clear: agents still cannot submit merge requests. The file itself remarks that all contributions must be reviewed in detail by humans, and this is basically the same policy used by the Linux kernel.
Note: I have not published blog posts about my academic papers over the past few years. To ensure that my blog contains a more comprehensive record of my published papers and to surface them for folks who missed them, I will periodically (re) publish blog posts about some older published projects. This post draws material from a previously published post by Kaylea Champion on the Community Data Science Blog.
Taboo subjects such as sexuality and mental health are as important to discuss as they are difficult to raise in conversation. Although many people turn to online resources for information on taboo subjects, censorship and low-quality information are common in search results. In two papers I recently published at CSCW both led by Kaylea Champion we presented a series of analyses showing how taboo shapes the process of collaborative knowledge building on English Wikipedia.
The first study is a quantitative analysis showing that articles on taboo subjects are much more popular and are the subject of more vandalism than articles on non-taboo topics. In surprising news, we also found that they were edited more often and were of higher quality!
The first challenge we faced in conducting this work was identifying taboo articles. Kaylea had a brilliant idea for a new computational approach to doing so without relying on our individual intuitions about what qualifies as taboo (something we understood would be highly specific to our own culture, class, etc). Her approach was to make use of an insight from linguistics: people develop euphemisms as ways to talk about taboos (i.e., think about all the euphemisms we ve devised for death, or sex, or menstruation, or mental health).
We used this insight to build a new machine-learning classifier based on English Wiktionary definitions. If a sense of a word was tagged as euphemistic, we treated the words in the definition as indicators of taboo. The end result was a series of words and phrases that most powerfully differentiate taboo from non-taboo. We then did a simple match between those words and phrases and the titles of Wikipedia articles. The topics were taboo enough that we were a little uncomfortable discussing them in our meetings! We built a comparison sample of articles whose titles are words that, like our taboo articles, appear in Wiktionary definitions. In the first paper, we used this new dataset to test a series of hypotheses about how taboo shapes collaborative production in Wikipedia. Our initial hypotheses were based on the idea that taboo information is often in high demand but that Wikipedians might be reluctant to associate their names (or usernames) with taboo topics. The result, we argued, would be articles that were in high demand but of low quality. We found that taboo articles are thriving on Wikipedia! In summary, we found that in comparison to non-taboo articles:
Image of the estimated qualiy of articles of the four articles in the second mixed-methods paper. Extreme dips reflect periods of frequent vandalism.The full citation for the papers are: (1) Champion, Kaylea, and Benjamin Mako Hill. 2023. Taboo and Collaborative Knowledge Production: Evidence from Wikipedia. Proceedings of the ACM on Human-Computer Interaction 7 (CSCW2): 299:1-299:25. https://doi.org/10.1145/3610090. (2) Champion, Kaylea, and Benjamin Mako Hill. 2024. Life Histories of Taboo Knowledge Artifacts. Proceedings of the ACM: Human-Computer Interaction 8 (CSCW2): 505:1-505:32. https://doi.org/10.1145/3687044.
We have also released replication materials for the paper, including all the data and code used to conduct the analyses.
This blog post and the paper it describes are collaborative work by Kaylea Champion and Benjamin Mako Hill.
A map of Vietnam with points of places we went to labeled. CARTO MAPTILER OPENSTREETMAP
A picture of the park we roamed around in Ho Chi Minh City. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
This is the restaurant Badri s friend took us to. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
One of the dishes we had in the restaurant. This one was especially tasty. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
One of the dishes we had in the restaurant. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
These noodles are called Pho and are very popular in Vietnam. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Interior of our train coach. Trains in Vietnam don t have side berths, unlike India. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
A picture of the berths from our coach. It had three tiers, similar to a 3 AC coach in Indian trains. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
The train had a cabin to put the bags in. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Nha Trang train station. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
I got a complimentary cup of green tea along with coffee in Nha Trang. In this trip, Badri and I found out that this is customary at local places in Vietnam. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Eggs being cooked on a pan for my order. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
The beach we went to in Nha Trang. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
This one was shot in the city center. In this trip, Badri and I found out that this is customary at local places in Vietnam. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Inside a Highlands Coffee cafe in Nha Trang. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
A coffee I got from Highlands Coffee in Nha Trang. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
The restaurant we went to in Nha Trang. The word Chay in the name means it was a vegan restaurant. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Soupy noodles we got at that restaurant. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Dry noodles we got at that restaurant. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
This was the place we had our coffee in Tra Kieu. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Photo of Badri with taxi driver. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
A picture of Tra Kieu area near the train station we got down at. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Our breakfast in Hoi An. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
A photo of the hostel we stayed in Hoi An. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Typical yellow house with gabled roof in Hoi An old town. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Egg coffee I had in Hoi An. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Bahn Bao in Hue. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Hot Pot. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Added soup to the noodles. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Steamed rolls made of rice flour. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Menu from a restaurant in Ho Chi Minh City with detailed description of the food. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Our berths in the train. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Egg coffee in Hanoi. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Hanoi train street is a tourist attraction in Hanoi. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
A picture of pho we had in Hanoi. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Bahn it is served packed in banana leaves. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
Bahn it. Photo by Ravi Dwivedi, released under CC-BY-SA 4.0.
WWW::Mechanize::Chrome library and its test suite. ThisResource was not cached errors duringsaveResources, we implemented a fully asynchronous fallback_saveResourceTree. By chaining_cached_document with DOM.getOuterHTMLfile:// access.File name too long errors,MAX_PATH limit is 260filenameFromUrl was hardened. The filenamedefault_executable_names was expanded to includeheadless_shell and search paths were updated to include/usr/lib64/chromium-browser/.DOM.documentUpdated events could invalidatenodeIds immediately after navigation, causing XPath queriessleep(0.25s) was added after page loads to ensure the DOMualarm was a blocker for Windows, wheret::helper::set_watchdog functionalarm() (seconds) on Windowsualarm (microseconds) on Unix-like systems, enablinglib/ and to always runmake clean and perl Makefile.PL to ensureMETA.json and META.yml reflect the newad2 Windows Server 2025 instance was restored andad2 Windows_future API.xpath, field,get, etc.) into thin wrappers around new non-blocking..._future counterparts. This moved timeout management tot/lib/t/helper.pm, was created tosafe_get,safe_xpath) were implemented there, usingFuture->wait_any to race asynchronous operations against# Example test helper implementation
sub safe_xpath
my ($mech, $query, %options) = @_;
my $timeout = delete $options timeout 5;
my $call_f = $mech->xpath_future($query, %options);
my $timeout_f = $mech->sleep_future($timeout)->then(sub Future->fail("Timeout") );
return Future->wait_any($call_f, $timeout_f)->get;
t/50-tick.t)WWW::Mechanize::Chrome::Node was storing[key, val, key, val]), which wast::helper that listens on an ephemeral port; the backgroundget_set_value_future non-blocking required first making its_field_by_name, asynchronous. This culminatedform_name,form_id, etc.) to use the new asynchronous_future lookups, which was a key step in mitigating the_process_eval_result helper to centralize the parsing ofRuntime.evaluate. This ensures consistenteval_in_page) and asynchronous (eval_future)$self and the $response object, creating aScalar::Util::weaken on both $self and any->then block that is stored on an object.
wantarray): AwantarrayFuture->then blocks. This causedxpath to return incorrect results (e.g., awantarray in the synchronous_future method, and# Synchronous Wrapper
sub xpath($self, $query, %options)
$options wantarray = wantarray; # 1. Capture
return $self->xpath_future($query, %options)->get; # 2. Pass
# Asynchronous Implementation
sub xpath_future($self, $query, %options)
my $wantarray = delete $options wantarray ; # 3. Retrieve
# ... async logic ...
return $doc->then(sub
if ($wantarray) # 4. Respect
return Future->done(@results);
else
return Future->done($results[0]);
);
decoded_content()__body_future. This was implemented by storing the$response-> __body_future ). To make this more robust,about:blankXMLSerializer to get the live DOM content.
Future->then. Callbacks were updated to use optionalsub($result = undef) ... ) to gracefullysetDocumentContent is parsed differently than contentdocument.evaluate) against the live DOM, bypassing the_future variants.t/lib/t/helper.pm), not in the core library.wantarrayFuture chain to ensure correctwarn, note, diag) should be$self->log('debug', ...)MutationObserver Saga (March 19)
With most of the library refactored to be asynchronous, one stubbornt/65-is_visible.t, continued to fail with timeouts.wait_until_visible polling logic with a moreMutationObserver.
repeat sleep loop with an event-drivenMutationObserver in JavaScript that would notify PerlcallFunctionOn_future.setTimeout, which expected milliseconds.MutationObserver sPromise would never resolve, even after thecheckVisibility JavaScript logic inside the observerconsole.log tracing, failed to resolve theChrome.pm module.MutationObserver approachMutationObserver, a strategic decision was made to revertMutationObserver implementation, when integrated viacallFunctionOn_future with awaitPromise,MutationObserver code fromWWW::Mechanize::Chrome.pm and restore the originalrepeat sleep polling mechanism. A stable,t/lib/t/helper.pmsafe_wait_until_* wrappers werewait_any andsleep_future) that raced against the underlying pollingt/78-memleak.t persisted, but only on the Windowsad2 environment. This required a different approach thanon_dialog event listener was not being broken on Windows,on_dialog(undef) in DESTROY) were notIO::Async event loop implementation on Windows, and theTest::Memory::Cycle module. The cycle report was identicalon_dialog(undef) call fromclose() to DESTROY().deleteing the listener and callbackDESTROY.$self->remove_listener and$self->target->unlisten in a mistaken attempt to findt/78-memleak.t was wrapped in a conditionalTODO block that only executes on Windowsif ($^O =~ /MSWin32/i)), formally acknowledging the bugprove --nocount --jobs 3 -I local/ -bl xt t directly. This-It/lib include path, whicht::helper module.Can't locate t/helper.pm in @INC.Makefile.PL revealed a custom MY::test block-It/lib flag into themake test command. This confirmed thatmake test is the correct, canonical way to run the test.github/workflows/linux.yml file was modified to replaceprove call with make test in theRun Tests step. This ensures the CI environment runs theWWW::Mechanize::Chrome test suite is now stable and
Linux kernel security modules provide a good additional layer of security around individual programs by restricting what they are allowed to do, and at best block and detect zero-day security vulnerabilities as soon as anyone tries to exploit them, long before they are widely known and reported. However, the challenge is how to create these security profiles without accidentally also blocking legitimate actions. For MariaDB in Debian and Ubuntu, a new AppArmor profile was recently created by leveraging the extensive test suite with 7000+ tests, giving good confidence that AppArmor is unlikely to yield false positive alerts with it.
AppArmor is a Mandatory Access Control (MAC) system, meaning that each process controlled by AppArmor has a sort of an allowlist called profile that defines all capabilities and file paths a program can access. If a program tries to do something not covered by the rules in its AppArmor profile, the action will be denied on the Linux kernel level and a warning logged in the system journal. This additional security layer is valuable because even if a malicious user found a security vulnerability some day in the future, the AppArmor profile severely restricts the ability to exploit it and gain access to the operating system.
AppArmor was originally developed by Novell for use in SUSE Linux, but nowadays the main driver is Canonical and AppArmor is extensively used in Ubuntu and Debian, and many of their derivatives (e.g. Linux Mint, Pop!_OS, Zorin OS) and in Arch. AppArmor s benefit compared to the main alternative SELinux (used mainly in the RedHat/Fedora ecosystem) is that AppArmor is easier to manage. AppArmor continues to be actively developed, with new major version 5.0 expected to arrive soon.
I also have some personal history contributing some notification handler scripts in Python and I also created the website that AppArmor.net still runs.
/var/log/audit/audit.log or run journalctl -ke --grep=apparmor.
A typical denial entry for MariaDB will look like this (split across multiple lines for legibility):
msg=audit(1700000000.123:456): apparmor="DENIED" operation="open"
profile="/usr/sbin/mariadbd" name="/custom/data/path/test.ibd" pid=1234
comm="mariadbd" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0open, mknod, file_mmap, file_perm)./usr/sbin/mariadbd profile).mariadbd).r for read, w for write)./etc/apparmor.d/ or drop a local customization file in at /etc/apparmor.d/local/. If the denied action looks malicious, the sysadmin should start a security investigation and if needed report a suspected zero-day vulnerability to the upstream software vendor (e.g. Ubuntu customers to Canonical, or MariaDB customers to MariaDB).
complain mode and iterated on the allowlist by running the full mariadb-test-run with all MariaDB plugins and features enabled until we had a comprehensive yet clean list of rules.
To be extra diligent, we also reworked the autopkgtest for MariaDB in Debian and Ubuntu CI systems to run with the AppArmor profile enabled and to print all AppArmor notices at the end of the run, making it easy to detect now and in the future if the MariaDB test suite triggers any AppArmor denials. If any test fails, the release would not get promoted further, protecting users from regressions.
While developing and triggering manual test runs we used the maximal achievable test suite with 7177 tests. The test is however so extensive it takes over two hours to run, and it also has some brittle tests, so the standard test run in Debian and Ubuntu autopkgtest is limited just to MariaDB s main suite with about 1000 tests. Having some tests fail while testing the AppArmor profile was not a problem, because we didn t need all the tests to pass we merely needed them to run as many code paths as possible to see if they run any system calls not accounted for in the AppArmor profile.
Note that extending the profile was not just mechanical copying of log messages to the profile. For example, even though a couple of tests involve running the dash shell, we decided to not allow it, as it opens too much of a path for a potential exploit to access the operating system.
The result of this effort is a modernized, robust profile that is now production-ready. Those interested in the exact technical details can read the Debian Bug#1130272 and the Merge Request discussions at salsa.debian.org, which hosts the Debian packaging source code.
complain mode, so AppArmor only logs would-be-denials without blocking anything. The AppArmor profile was switched to enforce mode only in the very latest MariaDB revision 1:11.8.6-4 in Debian, and a NEWS item issued to help increase user awareness of this change. It is also slated for the upcoming Ubuntu 26.04 Resolute Raccoon release next month, providing out-of-the-box hardening for the wider ecosystem.
While automated testing is extensive, it cannot simulate everything. Most notably various complicated replication topologies and all Galera setups are likely not covered. Thus, I am calling on the community to deploy this profile and monitor for any audit denials in the kernel logs. If you encounter unexpected behavior or legitimate denials, please submit a bug report via the Debian Bug Tracking System.
To ensure you are running the latest MariaDB version, run apt install --update --yes mariadb-server. To view the latest profile rules, run cat /etc/apparmor.d/mariadbd and to see if it is enforced review the output of aa-status. To quickly check if there were any AppArmor denials, simply run journalctl -k grep -i apparmor grep -i mariadb.
Next.