Linux

Making a Use-After-Free Leave Tracks

A driver crashed several calls after an object had been freed. The final bad pointer looked plausible, and ordinary logs only showed that teardown had happened sometime earlier. I needed the stale access to leave a clearer fingerprint.

I rebuilt the test kernel with CONFIG_DEBUG_SLAB. The slab allocator’s debugging checks and poisoning replace freed storage with a recognizable pattern instead of leaving yesterday’s fields looking valid. The next failure stopped looking like random corruption: the pointer led into an object full of poison bytes.

That didn’t identify the owner by itself. I decoded the complete oops against the matching unstripped vmlinux, then followed the call chain back to a timer callback. The timer retained the private pointer after the remove path had called kfree().

The repair was pleasantly unoriginal: prevent rearming, delete the timer with the synchronizing form, and only then free the object. I ran repeated load, activity, and unload cycles with slab debugging still enabled. I also forced probe failures after each acquisition to make sure partially built objects followed the same lifetime rules.

Poisoning is a diagnostic, not memory safety. It works when the freed bytes haven’t already been reused, and it makes a debug kernel slower. Here it turned a believable stale structure into an unmistakably dead one, which was exactly the clue I needed.

KDE 3.4 at Working Speed

KDE 3.4 brought Akregator into the standard release, so I moved one concrete morning routine into it: read a few dozen project feeds, stop halfway, and continue later through Kontact.

The first useful behavior is dull but essential: read state survives. I marked a few entries read in Akregator, closed Kontact, fetched another batch, and reopened it. Old articles stayed read and new ones remained easy to spot. A feed reader that forgets this turns every restart into archaeology.

Kontact integration matters because it doesn’t create a second, slightly different copy of the feeds. Opening the Akregator component in Kontact and the standalone application showed the same subscriptions and article state. Links still opened through KDE’s normal browser handling, so reading a project post didn’t require a new set of application preferences.

I also disconnected the network before opening cached entries. Text already fetched remained available, while a refresh failed visibly instead of silently marking feeds current. That’s the sort of release behavior I care about: the application is honest about which state is local and which depends on the network.

Duplicate handling needed a closer look. Several feeds republish an item with corrected text, and some are careless with identifiers. Akregator mostly kept the list stable rather than presenting every refresh as breaking news. Where a feed changed identity as well as content, the duplicate was at least explainable from the source.

There are rough edges. Feed folders and filters invite more organization than I want before coffee, and malformed feeds remain somebody’s debugging exercise. I resisted building a taxonomy and kept three folders.

This is a small addition to a large desktop release, but it shows the advantage of KDE’s shared parts. Akregator can live inside Kontact, hand links to the usual browser, and use familiar shortcuts without pretending feed reading is a separate universe.

After a week, the best result is that I can stop reading and trust the list when I return. That’s enough; the feeds don’t need to become a lifestyle.

A Stable Name for a Restless USB Disk

My backup script failed because the USB disk appeared under a different device node after a reboot. The script had one job and had apparently outsourced it to probe order.

I first added a loop that searched /dev/sd* and selected the first disk of roughly the right size. That is not identification; it is speed dating with block devices. One wrong match would turn a backup problem into a restoration problem.

The better route starts with the event. When the kernel discovers hardware, hotplug information reaches user space. sysfs exposes attributes and the device hierarchy. udev applies naming policy and creates nodes or symbolic links. A rule can therefore match something intrinsic to this disk, such as a serial attribute, rather than its temporary kernel name.

Before writing the rule, I inspected the sysfs path associated with the block device and walked upward to understand where the useful attribute lived. This distinction matters: a rule may receive attributes from the device itself and from parent devices, but blindly matching an attribute seen somewhere in /sys is an excellent way to create a rule that never fires.

The result was a stable symbolic link under /dev while the ordinary sd name remained available. My script uses the stable link and checks the filesystem before mounting it. udev supplies naming policy; it does not absolve the script from verifying what it is about to write.

I tested by unplugging the disk, attaching another one first, and reconnecting in different orders. Watching the hotplug environment and udev’s diagnostics was much faster than repeatedly editing a rule and staring at /dev with wounded optimism.

Cold-plug startup deserved the same test. A useful rule must behave consistently whether the disk is present during boot or attached later.

The division of responsibility is clean. The kernel reports what appeared and where it sits in the device model. User space decides what local name is useful. My machine’s nickname for a disk does not belong in a kernel driver.

Dynamic device management still has an intimidating number of moving parts, but the principle is reliable: match stable attributes, create a stable link, and keep transient enumeration out of scripts. Hardware order is an observation, not a promise.

Watching Linux History Move to Git

The interesting part of Git this week is no longer that it exists. Kernel developers are beginning to use it for actual Linux work, which changes the test from “can these objects be written?” to “can people exchange and trust history under pressure?”

I tried to imitate the old centralized habit by treating one repository as the place where truth lived and every other copy as a temporary client. That misses Git’s shape. Each repository can hold commits and their parent relationships. Fetching obtains objects and updates selected references; merging combines lines of development rather than asking a central server to manufacture history.

The kernel workflow makes the reason concrete. Maintainers can collect changes for their subsystem, preserve those commits, and pass a resulting line of history upward. The top-level maintainer can inspect and merge it. Signed e-mail and established review practices still matter; a fast object database does not decide whether a patch is wise.

I also learned not to confuse content identity with human trust. A hash can reveal that an object changed. It cannot tell me whether the author understood locking or whether I fetched from the person I intended. Technical integrity and project trust reinforce one another, but they are not synonyms.

Performance is already part of the appeal. Operations over the kernel tree need to be quick enough that developers use them freely. Cheap local history and branches encourage smaller experiments because recording work does not require a conversation with a remote machine.

That changes behavior as much as speed. A maintainer can inspect and organize work before publishing it instead of using the shared repository as a scratch pad.

The interface remains under construction, and I would not recommend that every project switch during lunch. Linux has an urgent need, unusually capable maintainers, and a willingness to work close to the machinery. That is a special environment, not a universal migration plan.

But adoption by the kernel gives Git a severe and useful proving ground. If it can preserve a large, branching C codebase while maintainers exchange changes independently, the design will have earned attention. I am keeping my test repository now. Calling it comfortable would be generous; calling it merely a toy would already be unfair.

Git Starts With Objects

The Linux kernel suddenly needs a new revision control system, and Linus has started writing one. That sentence sounds like the opening of either an excellent engineering story or a very efficient disaster. I downloaded Git to understand what was actually being built.

My naive attempt was to look for a familiar source-control interface. This first version doesn’t have one. It makes more sense as a handful of low-level programs over a content-addressed object store, plus an index used to assemble the next tree.

A file’s contents become a blob identified by its SHA-1 name. A tree names blobs and other trees. A commit object can point to a tree, identify a parent, and carry metadata. At this stage those raw objects are the useful thing to inspect; convenient names and comfortable workflows haven’t arrived yet.

The index is the interesting bit between the working directory and a tree object. update-cache records paths and their current object names in the index. write-tree turns that prepared index into a tree. It won’t quietly infer a polished commit operation from whatever happens to be in my directory.

I added a small file with update-cache, wrote the tree, and used cat-file to inspect what had been stored. The blob held content; the tree supplied the filename and mode. Changing one file produced a new blob and tree while unchanged blobs kept the same names. That reuse falls straight out of immutable, content-named objects.

I am not ready to entrust ordinary work to it. The commands are young, rough, and obviously aimed at solving the kernel project’s immediate emergency. Anyone claiming the user experience is finished has perhaps enjoyed too much fsck.

Still, the mechanism is compelling. commit-tree can wrap a prepared tree in a commit object, but the machinery remains exposed. It’s a very C-like start: small primitives, explicit input, and an operator who’s expected to pay attention.

For now I’m experimenting in a disposable directory and looking at .dircache/objects and the index rather than pretending this is a finished tool. Two days in, the raw storage model is already worth watching.