Fedora security Planet

Anatomy of a Jam Performance

Posted by Adam Young on February 20, 2024 10:53 PM

My Band, The Standard Deviants, had a rehearsal this weekend. As usual, I tried to record some of it. As so often happens, our best performance was our warm up tune. This time, we performed a tune called “The SMF Blues” by my good friend Paul Campagna.

<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="allowfullscreen" frameborder="0" height="329" src="https://www.youtube.com/embed/ZWs9G1dTfJA?feature=oembed" title="SMF Blues" width="584"></iframe>
</figure>

What is going on here? Quite a bit. People talk about Jazz as improvisation, but that does not mean that “Everything” is made up on the spot. It takes a lot of preparation in order for it to be spontaneous. Here are some of the things that make it possible to “just jam.”

Blues Funk

While no one in the band besides me knew the tune before this session, the format of the tune is a 12 bar blues. This is probably the most common format for a jam tune. A lot has been written on the format elsewhere, so I won’t detail here. All of the members of this group know a 12 bar blues, and can jump in to one after hearing the main melody once or twice.

The beat is a rock/funk beat set by Dave, our Drummer. This is a beat that we all know. This is also a beat that Dave has probably put 1000 hours into playing and mastering in different scenarios. Steve, on Bass, has played a beat like this his whole career. We all know the feel and do not have to think about it.

This song has a really strong turn around on the last two bars of the form. It is high pitched, repeated, and lets everyone know where we are anchored in the song. It also tells people when a verse is over, and we reset.

Signals

The saxophone plays a lead role in this music, and I give directions to the members of the band. This is not to “boss” people around, but rather to reduce the number of options at any given point so that we as a unit know what to do. Since we can’t really talk in this scenario, the directions have to be simple. There are three main ways I give signals to the band.

The simplest is to step up an play. As a lead instrument, the saxophone communicates via sound to the rest of the band one of two things; either we are playing the head again, or I am taking a solo. The only person that really has to majorly change their behavior is Adam 12 on Trombone. Either he plays the melody with me or he moves into a supporting role. The rest of the band just adjusts their energy accordingly. We play louder for a repetition of the head, and they back off a bit for a solo.

The second way I give signals to the band is by direct eye contact. All I have to do is look back at Dave in the middle of a verse to let him know that the next verse is his to solo. We have played together long enough that he knows what that means. I reinforce the message by stepping to the side and letting the focus shift to him.

The third way is to use hand gestures. As a sax player, I have to make these brief, as I need two hands to play many of the notes. However, there are alternative fingerings, so for short periods, I can play with just my left hand, and use my right to signal. The most obvious signal here is the 4 finger hand gesture I gave to Adam 12 that we are going to trade 4s. This means that each of us play for four measures and then switch. If I gave this signal to all of the band, it would mean that we would be trading 4s with the drums, which we do on longer form songs. Another variation of this is 2s, which is just a short spot for each person.

One of the wonderful thing about playing with this band is how even “mistakes” such as when i tried to end the tune, and no one caught the signal…and it became a bass solo that ended up perfectly placed. Steve realized we all quieted out, and that is an indication for the Bass to step up, and he did.

Practice Practice Practice

Everyone here knows their instrument. We have all been playing for many decades, and know what to do. But the horn is a harsh mistress, and she demands attention. As someone once said:

Skip a day and you know. Skip two days and your friends know. Skip three days and everyone knows.

Musical Wisdom from the ages

Adam 12 is the newest member of the band. It had been several years since he played regularly before he joined us. His first jam sessions were fairly short. We have since heard the results of the hard work that he has put in.

I try to play every day. It completes with many other responsibilities and activities in modern life. But my days seems less complete if I did not at least blow a few notes through the horn.

Listening

Music is timing. Our ears are super sensitive to changes in timing, whether at the micro level, translating to differences in pitch, or the macro level, with changes in tempo…which is just another word for time. Dave is the master of listening. He catches on to a pattern one of us it playing and he works it into his drumming constantly. Steve is the backbone of the band. Listening to the bass line tells us what we need to know about speed and location in the song. The more we play together, the more we pick up on each others cues through playing. The end effect is that we are jointly contributing to an event, an experience, a performance.

Episode 416 – Thomas Depierre on open source in Europe

Posted by Josh Bressers on February 19, 2024 12:00 AM

Josh and Kurt talk to Thomas Depierre about some of the European efforts to secure software. We touch on the CRA, MDA, FOSDEM, and more. As expected Thomas drops a huge amount of knowledge on what’s happening in open source. We close the show with a lot of ideas around how to move the needle for open source. It’s not easy, but it is possible.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3321-1" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_416_Thomas_Depierre_on_open_source_in_Europe.mp3?_=1" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_416_Thomas_Depierre_on_open_source_in_Europe.mp3</audio>

Show Notes

Swimming positions improvements

Posted by Adam Young on February 16, 2024 06:58 PM

I have been getting in the pool for the past couple of months, with a goal of completing a triathalon this summer. Today I got some pointers on things I need to improve on in my freestyle technique.

Kick

My kick needs some serious work. I am pulling almost exclusively with my arms. As Jimmy (the lifeguard and a long time swim coach) said, “You’re killing yourself.”

He had me do a drill with just a kickboard. “If your thighs are not hurting you are doing it wrong.” I focused on barely breaking the surface with my heels, pointing my toes, and keeping my legs relatively straight…only a slight bend.

Next he had me do a lap with small flippers. “You shouldn’t fell like you are fighting them.” The force you to point your toe. It felt almost too easy. We ran out of time for me to try integrating it into a regular stroke.

For weight lifting, he recommended squats.

For a sprint he recommended 3 kicks per stroke/6 per pair. For longer courses, two kicks per stroke. I think I will shoot for 2/ stroke, as I am going for 1/2 mile total.

Breathing

Improving my kick will improve my whole body position, including my breathing. It seems I am pulling my head too far out of the water, mainly because my legs are dropping. Although the opposite is true, too: pulling my head too far out of the water is causing my legs to drop. The two should be fixed together.

Arm Entry

One other swimmer at the pool that I asked for advice told me to “lead with my elbows” and then to think about entering the water “like a knife through butter”. Jimmy added that I should be reaching “long and lean.” Like a fast sailboat.

After that, the stroke should go out, and then finish in an S.

I think I need to glide more during the initial entry of the arm into the water.

Jimmy recommended a drill, either using a kickboard or a ring, and holding that out in front, and passing it from hand to hand.

Head position

I should be looking down and to the front,while the the top of my head breaks the surface.

CentOS Connect 2024 report

Posted by Alexander Bokovoy on February 13, 2024 07:25 AM

February 1st-4th I participated in two events in Brussels: CentOS Connect and FOSDEM. FOSDEM is getting closer to its quarter a century anniversary next year. With 67 mini-conferences and another 30 events around it, it is considered one of the largest conferences in Europe, any topic included. This report is about CentOS Connect.

CentOS Connect

CentOS Connect was a two-day event preceding FOSDEM. Organized by the CentOS project, it brought together contributors from multiple projects around CentOS Stream upstreams (such as Fedora Project) and downstreams (from Red Hat Enterprise Linux, AlmaLinux, Rocky Linux, and others), long-time users and community members. A lot of talks were given on both days and several special interest groups (SIGs) ran their workshops on the first day.

CentOS Integration SIG

I have attended a workshop organized by the CentOS Integration SIG. The focus of this group is to define and run integration tests around CentOS Stream delivery to the public. While CentOS Stream composes are built using the messages on how RHEL next minor version is composed after being thoroughly tested by Red Hat’s quality engineering group, there is a value in testing CentOS Stream composes by other community members independently as their use cases might differ. Right now the set of tests is defined as a t_functional suite maintained by the CentOS Core SIG but this suite is not enough for the complex scenarios.

The Integration SIG is looking at improving the situation. Two projects were present and interested in this work: RDO (RPM-based distribution of OpenStack) and RHEL Identity Management. Both teams have to deal with coordinated package deliveries across multiple components and both need to get multi-host deployments tested. RDO can be treated as a product built on top of CentOS Stream where its own RDO deliveries are installed on top of CentOS Stream images. RHEL Identity Management (IdM), on the other hand, is a part of RHEL. It is famously known as a ‘canary in the RHEL mine’ (thanks to Stephen Gallagher’s being poetic a decade ago): if anything is broken in RHEL, chances are it will be visible in RHEL IdM testing. With RHEL IdM integration scope expanding to provide passwordless desktop login support, this becomes even more important and also requires multi-host testing.

CentOS Integration SIG’s proposal to address these requirements is interesting. Since CentOS Stream compose event is independent of the tests, a proposal by Aleksandra Fedorova and Adam Samalik is to treat the compose event in a way similar to a normal development workflow. Producing CentOS Stream compose would generate a merge request of a metadata associated with it to a particular git repository. This merge request then can be reacted to by the various bots and individuals. Since CentOS Stream compose is public, it is already accessible to third-party developers to run their tests and report back the results. This way qualification of the compose promotion to CentOS Stream mirrors can be affected by all parties and will help to keep already published composes in a non-conflicting state.

Since most of the projects involved already have their own continuous integration systems, adding another trigger for those would be trivial. For RHEL IdM and its upstream components (FreeIPA, SSSD, 389-ds, Dogtag PKI, etc.) it would also be possible finally to react to changes to CentOS Stream well ahead of time too. In the past this was complicated by a relative turbulence in the CentOS Stream composes early in RHEL next minor release development time when everybody updates their code and stabilization needs a lot of coordination. I am looking forward to Aleksandra’s proposal to land in the Integration SIG’s materials soon.

Update: Aleksandra has published her proposal at the Fedora Discussion board

CentOS Stream and EPEL

Two talks, by Troy Dawson and Carl George, described the current state of EPEL repository and its future interactions with CentOS 10 Stream. Troy’s discussion was fun, as usual: a lot of statistics obtained from the DNF repository trackers shows that old habits are hard to get rid off and moving forward is a struggle to many users despite security and supportability challenges with older software. Both CentOS 7 and CentOS 8 Stream end of life dates are coming in 2024, adding enough pressure themselves to that.

There are interesting statistics from the EPEL evolution. In August 2023 at Flock to Fedora conference Troy and Carl pointed out that 727 packagers maintained 7298 packages in EPEL 7, 489 packagers handled 4968 packages in EPEL 8, and 396 packagers were handling 5985 packages in EPEL 9. Half a year later we have 7874 packages in EPEL 7, 5108 packages in EPEL 8, and 6868 packages in EPEL 9. Pace seems to pick up EPEL 9 with upcoming end of life dates for older versions. Since soon only EPEL 9 and EPEL 10 would be actively built, there are probably more packagers that would be active in them as well.

EPEL 10 is coming soon. It will bring a slight difference in package suffixes and overall reduction of complexity to packagers. It is great to see how close EPEL work tracks to ELN activities in Fedora. One thing worth noting is that every Fedora package maintainer is a potential EPEL maintainer as well because EPEL reuses Fedora infrastructure for package maintenance. Even if someone is not maintaining EPEL branches on their Fedora packages (I am not doing that myself – my packages are mostly in RHEL), it allows easy jump-in and collaboration. After all, if packages aren’t in RHEL but are in Fedora, their EPEL presence is just one git branch (and Fedora infrastructure ticket) away.

20 years of CentOS project

First day of the CentOS Connect event ended with a party to celebrate 20 years of the CentOS Project. First release (“CentOS version 2”) went out on May 14th, 2004 but since CentOS Connect is the closest big event organized by the project this year, getting a lot of contributors together to celebrate this anniversary seemed appropriate. A huge cake was presented, so big that it wasn’t possible to consume it completely during the party. It was delicious (like a lot of Belgian chocolate!) and next day coffee breaks allowed me to enjoy it a lot.

FreeIPA and CentOS project infrastructure

My own talk was originally planned to gather feedback from all projects which build on top of CentOS as they use a very similar infrastructure. CentOS Project infrastructure is shared with Fedora Project which is built around FreeIPA as a backend and Noggin as a user management frontend. I asked in advance for some feedback from Fedora, CentOS, AlmaLinux, and RockyLinux infrastructure teams and haven’t gotten that much which prompted my own investigation. It is not an easy job since most organizations aren’t really interested in telling the world details of their core infrastructure. Hope was that I’d be able to see real world usage and maybe take some lessons from it back to the development teams.

While working on my talk, we also experienced an outage in Fedora infrastructure related to the upgrade of the FreeIPA setup used there. My team has been helping Fedora infrastructure administrators so I finally got the feedback I was looking for. That led to several fixes upstream and they have recently been backported to RHEL and CentOS Stream as well. However, the overall lack of feedback is concerning – or at least I thought so.

During CentOS Connect I had the opportunity to discuss this with both AlmaLinux (Jonathan) and RockyLinux (Luis) projects’ sysadmins. “It just works” is a common response I get. Well, that’s nice to hear but what was more exciting to hear is that these projects went a bit further than we did in Fedora and CentOS Stream with their environments. Luis has published the whole RockyLinux infrastructure code responsible for FreeIPA deployment. It is based heavily on ansible-freeipa, reuses the same components we developed for Fedora Infrastructure. Rocky also runs FreeIPA tests in OpenQA instance, similarly to Fedora, and hopefully Luis would contribute more tests to cover passwordless login, already available in CentOS Stream. This would be a very welcome contribution in the light of the Integration SIG activities, helping us to test more complex scenarios community-wide. AlmaLinux infrastructure also uses ansible-freeipa but the code is not publicly available, for whatever reason. Jonathan promised to rectify this problem.

Hallway tracks

I had a number of discussions with people from all kinds of CentOS communities. FreeIPA sits at a unique position by providing secure infrastructure to run POSIX workloads and linking it with modern requirements to web authentication. Our effort to improve passwordless login to Linux environments with reuse of Kerberos to propagate authorization state across multiple machines helps to solve the ‘between the worlds’ problems. That is something that many academic institutions have noticed already and many talks I had in the hallways were related to it.

Episode 415 – Reducing attack surface for less security

Posted by Josh Bressers on February 12, 2024 12:00 AM

Josh and Kurt talk about a blog post explaining how to create a very very small container image. Generally in the world of security less is more, but it’s possible to remove too much. A lot of today’s security tooling relies on certain things to exist in a container image, if we remove them we could actually result in worse security than leaving it in. It’s a weird topic, but probably pretty important.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3316-2" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_415_Reducing_attack_surface_for_less_security.mp3?_=2" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_415_Reducing_attack_surface_for_less_security.mp3</audio>

Show Notes

Episode 414 – The exploited ecosystem of open source

Posted by Josh Bressers on February 05, 2024 12:00 AM

Josh and Kurt talk about open source projects proving builds, and things nobody wants to pay for in open source. It’s easy to have unrealistic expectations for open source projects, but we have the open source that capitalism demands.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3310-3" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_414_The_exploited_ecosystem_of_open_source.mp3?_=3" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_414_The_exploited_ecosystem_of_open_source.mp3</audio>

Show Notes

Vector times Matrix in C++

Posted by Adam Young on February 03, 2024 11:56 PM

The basic tool for neural networks is: vector times matrix equals vector. The first vector is your input pattern, the second is your output pattern. Stack these in a series and you have a deep neural network. The absolute simplest implementation I could find for this is in C++ using boost.

Here it is:



#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

int main () {
    using namespace boost::numeric::ublas;
    matrix<double> m (3, 3);
    vector<double> v (3);
    for (unsigned i = 0; i < std::min (m.size1 (), v.size ()); ++ i) {
        for (unsigned j = 0; j < m.size2 (); ++ j)
            m (i, j) = 3 * i + j;
        v (i) = i;
    }


     vector<double> out1 = prod (m, v);
     vector<double> out2 = prod (v, m);

    std::cout << out1 << std::endl;
    std::cout << out2 << std::endl;


}

This is almost verbatim the sample code from Boost BLAS. Scroll down to the prod example. So now the question is, how does one go from that to a neural network? More to come.

Another question that comes to my mind is how would you optimize this if you have a vector based co-processor on your machine?

A Different Key Setup for Chords

Posted by Adam Young on January 29, 2024 01:45 AM

For my birthday last year, my family got me an accordion. Yes, I am one of those people that collect musical instruments, not for their monetary value but because I enjoy trying them out. I spent some time trying to wrap my mind and my hands around the one button chord set up on the side. I know there are masters out there that have developed a set of techniques, but for those of use from other instruments, the arraignment of notes and chords in a cycle of fifth is challenging.

It got me thinking about how else you could arrange them. This might also be somewhat inspired by guitar and bass setups, but here is what I came up with:

Start with a chromatic arrangement like this:

<figure class="wp-block-table">
G#A#C#E
GACD#
FG#BD
EGA#C#
D#F#AC
DFG#B
C#EGA#
CD#F#A
BDFG#
A#C#EG
ACD#F#
<figcaption class="wp-element-caption">Chromatic arrangement</figcaption></figure>

Assume that this is a keyboard with the bottom left nearest to you, pointing toward the ground. The Top right is pointing away and skyward. You put your pinky on A, ring finger on C, middle finger on D#, and index finger on F#. If you play those four notes, you get a diminished 7th chord.

What should be apparent from this set up is that you can play all forms of 7th chords with your pinky on the root note. To play A Major seventh, pinky on A, ring on C#, middle on E, Index on G#. If each button is a centimeter apart, Your index finger reaches at most 4 cm from lowest to highest.

To play an A augmented pinky on A. Ring on C#, Middle on F. Your index could play the root an octave up.

This same pattern would work up to F. We’d need to extend up four notes in each column to get something that would work for each chord.

Lets move our index finger to the A four notes from the bottom. From here, an Adom7 chord in second inversion could be played with pinky (P) on C#, ring(R) on E, middle(M) on G. A Maj 7moves the ring one more space up, which should still be comfortable to reach.

Lets say you have to play a I-vi-ii-V7 progression. We’ll do this in C major, both because it is well known and because it is in the middle of our keyboard. Lets say we start with the Cmaj7 in root position. Using the first letter of each finger as short hand: P-C, R-E, M-G, I-B.

<figure class="wp-block-image size-large"></figure>

(I realize now that all the images are 180 flipped from how I described it above. Just treat it like guitar tab….)

Now to Amin7, we’ll play it as I noted above: Index stays on the A. All other fingers stay in position: P-C, R-E, M-G, I-A.

<figure class="wp-block-image size-large"><figcaption class="wp-element-caption">A MINOR</figcaption></figure>

Now, to move to a Dmin7, we leave the Pinky and the Index in place (P-C, I-A) Ring finger and Middle fingers move down two keys to D and F.  Seems pretty efficient P-C, R-F, M-F I-A.

<figure class="wp-block-image size-large"></figure>

That leaves the G7. For this we want to use a third inversion, with the middle finger staying on the G. The Ring finger extends up to the B. The Pinky extends up to the D. The Ring finger extends up to the F. Again, seems pretty efficient.

<figure class="wp-block-image size-large"></figure>

I thik I ma going to do some paper prototyping here.

And with gratitude I think this is a more efficient G7 position.

<figure class="wp-block-image size-large"><figcaption class="wp-element-caption">Alternative voicing for G7.</figcaption></figure> <figure class="wp-block-image size-large"><figcaption class="wp-element-caption">My Accordion. Ain’t she pretty?</figcaption></figure>

Episode 413 – PyTorch and NPM get attacked, but it’s OK

Posted by Josh Bressers on January 29, 2024 12:00 AM

Josh and Kurt talk about an attack against PyTorch and NPM. The PyTorch attack shows the difficulty of operating a large open source project. The NPM situation continues to show the difficulty in trying to backdoor open source. Many people are watching, and it only takes one person to notice a problem and report it, and we all benefit.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3303-4" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_413_PyTorch_and_NPM_get_attacked_but_its_OK.mp3?_=4" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_413_PyTorch_and_NPM_get_attacked_but_its_OK.mp3</audio>

Show Notes

Episode 412 – Blame the users for bad passwords!

Posted by Josh Bressers on January 22, 2024 12:00 AM

Josh and Kurt talk about the 23andMe compromise and how they are blaming the users. It’s obviously the the fault of the users, but there’s still a lot of things to discuss on this one. Every company has to care about cybersecurity now, even if they don’t want to.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3298-5" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_412_Blame_the_users_for_bad_passwords.mp3?_=5" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_412_Blame_the_users_for_bad_passwords.mp3</audio>

Show Notes

Episode 411 – The security tools that started it all

Posted by Josh Bressers on January 15, 2024 12:00 AM

Josh and Kurt talk about a grab bag of old technologies that defined the security industry. Technology like SELinux, SSH, Snort, ModSecurity and more all started with humble beginnings, and many of them created new security industries.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3292-6" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_411_The_security_tools_that_started_it_all.mp3?_=6" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_411_The_security_tools_that_started_it_all.mp3</audio>

Show Notes

Print the line after a match using AWK

Posted by Adam Young on January 08, 2024 06:46 PM

We have an internal system for allocating hardware to developers on a short term basis. While the software does have a web API, it is not enabled by default, nor in our deployment. Thus, we end up caching a local copy of the data about the machine. The machine names are a glom of architecture, and location. So I make a file with the name of the machine, and a symlink to the one I am currently using.

One of the pieces of information I need out of this file is the IP address for ssh access. The format is two lines in the file, like this:

BMCIP
10.76.244.85
SYSTEMIP
10.76.244.65

While the SYSTEMIP is an easy regular expression match, what I need is the line after the match, and that is a little less trivial. Here is what I have ended up with (using this post as a reference).

awk 'f{print; f=0};/SYSTEMIP/{f=1}' current_dev 

Which produces the expected output:

10.76.244.65

Running a UEFI program upon reboot

Posted by Adam Young on January 08, 2024 03:51 AM

Linux is only one of the Operating Systems that our chips need to support. While some features need a complete OS for testing, we want to make sure that features are as tested as possible before we try to debug them through Linux.

My current code implements has to talk to the firmware. Thus we need to have a responder in the firmware. Testing this from Linux has to go through the entire Linux networking stack.

The developers of the firmware already have to deal with UEFI. UEFI is installed with the firmware. Since writing UEFI apps is basically like writing DOS apps (according to Ron Minnich) it is not a huge demand on our Firmware team to have them use UEFI as the basis for writing thei test code. Thus, they produced a simple app called RespTest.efi That checks that their code does what they expect it to do.

The normal process is that they boot the UEFI shell, switch to the file system, and copy up the Executable via tftp, Once it is on the system, they run it manually. After the first time the executable is leaded, the executable is persisted on the system. Thus, to run it a second or third time, after, say, a change to the firmware, can be automated from the operating system.

ls /boot/efi/
EFI  ResponderTest.efi  spinor.img

The above was executed from a Linux system running that has the efi partition mounted in /boot/efi. The RespTest.efi binary was copied up using tftp.

To see the set of UEFI boot options, we can use efibootmgr. These are mostly various flavors of PXE

efibootmgr
BootCurrent: 0001
Timeout: 10 seconds
BootOrder: 0000,0001,0002,0003,0004,0005,0006,0007,0008,0009,000A
Boot0000* UiApp	FvVol(5c60f367-a505-419a-859e-2a4ff6ca6fe5)/FvFile(462caa21-7614-4503-836e-8ab6f4662331)
Boot0001* Fedora (Samsung SSD 970 EVO Plus 250GB)	PcieRoot(0x60000)/Pci(0x1,0x0)/Pci(0x0,0x0)/NVMe(0x1,00-25-38-5A-91-51-38-0A)/HD(1,GPT,4c1510a2-110f-492f-8c64-50127bc2e552,0x800,0x200000)/File(\EFI\fedora\shimaa64.efi) File(.????????)
Boot0002* UEFI PXEv4 (MAC:0C42A15A9B28)	PcieRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x0)/MAC(0c42a15a9b28,1)/IPv4(0.0.0.00.0.0.0,0,0){auto_created_boot_option}
...
Boot0009* UEFI HTTPv6 (MAC:0C42A15A9B29)	PcieRoot(0x0)/Pci(0x1,0x0)/Pci(0x0,0x1)/MAC(0c42a15a9b29,1)/IPv6([::]:<->[::]:,0,0)/Uri(){auto_created_boot_option}
Boot000A* UEFI Shell	FvVol(5c60f367-a505-419a-859e-2a4ff6ca6fe5)/FvFile(7c04a583-9e3e-4f1c-ad65-e05268d0b4d1)

Lets say I want to boot to the UEFI shell next time. Since that has an index of 000A, I can run the following command to tell UEFI to boot to the shell once and only once. After that it will return to the default order:

efibootmgr –bootnext 000A

Here are the first few lines of output from that command;

# efibootmgr --bootnext 000A
BootNext: 000A
BootCurrent: 0001
Timeout: 10 seconds

If I want to add an addition boot option, I can use the –create option. To tell it to boot the ResponderTest,efi executable:

efibootmgr efibootmgr --create -d /dev/nvme0n1p1 --label RespTest -l RespTest.efi

The last line of output from that command is:

Boot000B* RespTest	HD(1,GPT,4c1510a2-110f-492f-8c64-50127bc2e552,0x800,0x200000)/File(RespTest.efi)efibootmgr

If I then want to make UEFI select this option upon next boot…

# efibootmgr --bootnext 000B
BootNext: 000B
BootCurrent: 0001
Timeout: 10 seconds

Note that the executable is in /boot/efi mounted on the Linux filesystem, but that will be the EF0: in UEFI. If you wish to put something further down the tree, you can, but remember that UEFI uses reverse slashes. I think it would look something like this…but I have not tried it yet:

efibootmgr efibootmgr –create -d /dev/nvme0n1p1 –label RespTest -l EFI\\RespTest.efi

Note the double slash to avoid Linux escaping….I think this is necessary.

Episode 410 – Package identifiers are really hard

Posted by Josh Bressers on January 08, 2024 12:00 AM

Josh and Kurt talk about package identifiers. We break this down in the context of an OpenSSF response to a CISA paper on software identifications. The identifiers that get all the air time are purl, CPE, SWID, and OmniBOR. This is a surprisingly complex problem space. It feels easy, but it’s not.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3289-7" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_410_Package_identifiers_are_really_hard.mp3?_=7" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_410_Package_identifiers_are_really_hard.mp3</audio>

Show Notes

On The Lineageos User Exposure Window

Posted by Robbie Harwood on January 07, 2024 05:00 AM

Unfortunate scheduling means that LineageOS users are exposed to publicly disclosed vulnerabilities for typically nine days per month. Here's why, and what I (a user who is otherwise uninvolved in the project) think could be done to improve the situation.

Per official Android documentation:

Important: The Android Security Bulletins are published on the first Monday of each month unless that Monday falls on a holiday. If the first Monday of the month is a holiday the bulletins will be published on the following work day.

Holiday time off makes sense for human reasons, though it makes release days inconsistent. (And I assume we're talking US holidays because Google, though this isn't stated.) Adherence to this isn't great - most egregiously, something happened that resulted in a March 13, 2023 release which is probably the largest slip since August 13, 2015 (which is far back as the table goes). But I've worked in security engineering long enough to know that sometimes dates will slip, and I'm sure it's not intentional. Clerical errors like the November 2023 bulletin date are also inevitable.

But let's assume for the sake of simplicity that disclosure happens as written: on the first Monday of the month (or the following day) a bulletin is published listing the CVEs included, their type/severity, and which Android (i.e., AOSP) versions are affected. Importantly absent here are the patches for these vulnerabilities, which per the bulletin boilerplate take 2 days to appear. So what's the point of the bulletin?

In any case, this means that patches won't be available until Wednesday or Thursday. Lineage posts updates on Friday; per datestamps, these updates are built on Thursdays. This means that in order to have the security fixes (and security string) in the next Lineage update, there is less than a day's window to gather patches, backport them, post pull requests, run CI, get code review, etc., before the weekly build is made - a seemingly herculean feat. And sometime months, it won't be technically possible at all.

So since patches will not land in the next release, all users of official builds are exposed to publicly disclosed vulnerabilities for typically nine days. (I think it's 8-10, but I don't discount off-by-one, and that also relies on Lineage not slipping further; everyone's human and it does happen, especially on volunteer projects.)

Clearly, the schedule is a problem. Here are my initial thoughts on how this might be addressed:

  1. Release Lineage updates on a different day. If it takes four days to run through the backport+review+build pipelines, then plan to release on Monday. Users will still be exposed for the length of time it takes to backport+review+build.
  2. Add Lineage to the embargo list. This would mean that backport and review could take place prior to public disclosure, and so including the security fixes in the upcoming Friday update becomes doable. Users are still exposed for 2 days, but that's way better than 9. (I am not involved in the Lineage project so it's possible they already are included, but that seems unlikely given security update PRs are not usually sent on the day code becomes publicly available.)
  3. Stop the bulletin/patch desync. I cannot come up with a good reason why the security bulletin and patches are released at different times, let alone releasing the bulletin before the patches. This makes reasoning about fix availability unnecessarily complicated. However, it would probably require Google to care.
  4. Update Lineage less frequently. It seems like the least amount of work, but if, e.g., Lineage released once per month, then the day of the release could be whenever the security fixes for the month land. This is also helpful beccause it minimizes the number of times that flashing needs to occur. (But that may be a larger discussion for a different post.)

These are not mutually exclusive, either.

To close out, I need to head off something that I am quite sure will come up. Yes, I am capable of running my own custom Android builds and kernel trees. I do not want to do this, and more importantly, users who are not developers by definition cannot do it. That is to say: OTA updates and official builds are the most important versions of the project, not whatever custom stuff we make. (After all, if that weren't the case, there wouldn't be five major forks over the signature spoofing decision.)

How Did I break my Code

Posted by Adam Young on January 04, 2024 11:17 PM

Something I did in a commit broke my code. I have a git bisect that shows me the last good commit and the first bad one.

The code in question is a device driver for MCTP over PCC. MCTP is a network protocol used to have different components on a single system talk to each other. PCC is a shared buffer mechanism with a “doorbell” or register-that-triggers-an-interrupt. Another team needs to use this driver.

In looking through the output, a co-worker stated “it looks like you are sending the wrong buffer.” I suspected he was correct.

The buffers are pulled from ACPI information in a table specific to PCC, called the PCCT.

This is from the PCCT, which is common to both the good and bad run, and shows the machine (physical) addresses of the memory.


03 [Extended PCC Master Subspace]
               Base Address       = 00004000000D4004


04 [Extended PCC Slave Subspace]
               Base Address       = 00004000000D4404

Here is output data I get from a run of code from tip of tree.




[  644.338469] remap_pcc_comm_addresses outbox pcc_chan->shmem_base_addr = 4000000d4004 mapped to  ffff800080621004
[  644.348632] remap_pcc_comm_addresses inbox pcc_chan->shmem_base_addr = 4000000d4404 mapped to ffff80008061f404

[  644.338469] remap_pcc_comm_addresses outbox pcc_chan->shmem_base_addr = 4000000d4004 mapped to  ffff800080621004
[  644.348632] remap_pcc_comm_addresses inbox pcc_chan->shmem_base_addr = 4000000d4404 mapped to ffff80008061f404
 



 
[  828.014307] _mctp_get_buffer pcc_chan->shmem_base_addr = 1  ptr = 000000007f3ab582 
[  828.021950] mctp_pcc_tx buffer = ffff80008061f404

What I see is that I am sending data on the inbox address, not the outbox. So where did I swap it?

541392a553a2c2b7f741d89cff0ab8014a367299 is the first bad commit.

Lets take a look at the code in that commit. The diff shows a lot of changes in _mctp_get_buffer. Here’s what it looks like in non-diff form

static unsigned char * _mctp_get_buffer (struct mbox_chan * chan){
        void __iomem * pcc_comm_addr;
         
        struct pcc_mbox_chan * pchan = (struct pcc_mbox_chan *) chan;

        
        if (pchan == mctp_pcc_dev->out_chan){
                pcc_comm_addr =  mctp_pcc_dev->pcc_comm_outbox_addr;
        }else{
                pcc_comm_addr = mctp_pcc_dev->pcc_comm_inbox_addr;
        }
        pr_info("%s pcc_chan->shmem_base_addr = %llx  ptr = %p \n",
                        __func__, pchan->shmem_base_addr, pcc_comm_addr );
        return (unsigned char *  )pcc_comm_addr;
} 

How could this fail? Well, what if the cast from chan to pchan is bogus? If that happens, the if block will not match, and we will end up in the else block.

Why would I cast like that? Assume for a moment (as I did) that the definitions looked like this:

struct   pcc_mbox_chan {
 struct mbox_chan  chan;
}

Ignore anything after the member variable chan. This is a common pattern in C when you need to specialize a general case.

This is not what the code looks like. Instead, it looks like this:

struct   pcc_mbox_chan {
 struct mbox_chan*  chan;
}

The structure that chan points to was allocated outside of this code, and thus cannot be cast.

The else block always matched.

The reason the old code ran without crashing is it was getting a valid buffer, just not the right one. I was trying to send the “outbox” buffer, but instead sent the “inbox” buffer.

Here is the corrected version of the if block.

if (chan == mctp_pcc_dev->out_chan->mchan){
        pcc_comm_addr = mctp_pcc_dev->pcc_comm_outbox_addr;
}else if (chan == mctp_pcc_dev->in_chan->mchan){
        pcc_comm_addr = mctp_pcc_dev->pcc_comm_inbox_addr;
}
if (pcc_comm_addr){
        pr_info("%s buffer ptr = %px \n",__func__, pcc_comm_addr );
        return (unsigned char * )pcc_comm_addr;
}

What made this much harder to debug is the fact that the “real” system I was testing against had changed and I was not able to test my code against it for a week or so, and by then I had added additional commits on top of the original one. This shows the importance of testing early, testing often, and testing accurately.

To give a sense of how things got more complicated, here is the current version of the get_buffer function:

static unsigned char * _mctp_get_buffer (struct mbox_chan * chan){
        struct mctp_pcc_ndev * mctp_pcc_dev = NULL;
        struct list_head *ptr;
        void __iomem * pcc_comm_addr = NULL;
        list_for_each(ptr, &mctp_pcc_ndevs) {
                mctp_pcc_dev = list_entry(ptr,struct mctp_pcc_ndev, head);
        
                if (chan == mctp_pcc_dev->out_chan->mchan){
                        pcc_comm_addr =  mctp_pcc_dev->pcc_comm_outbox_addr;
                }else if (chan == mctp_pcc_dev->in_chan->mchan){
                        pcc_comm_addr = mctp_pcc_dev->pcc_comm_inbox_addr;
                }
                if (pcc_comm_addr){
                        pr_info("%s buffer ptr = %px \n",
                                __func__, pcc_comm_addr );
                        return (unsigned char *  )pcc_comm_addr;
                }
        }
        //TODO this should never happen, but if it does, it will
        //Oops.  Handle the error better
        pr_err("%s unable to match mctp_pcc_ndev", __func__);
        return 0;
}

Why is it now looking through a list? One of the primary changes I had to make was to move the driver from only supporting a single device to supporting multiple. Finding which buffer to get from struct mbox_chan is again going from general to specific.

This code is still in flight. The list lookup may well not survive the final cut, as there is possibly a better way to get the buffer from the original structure, but it is not clear cut. This works, and lets the unit tests continue to pass. This allows the team to make progress. It might be technical debt, but that is necessary part of a complicated development integration process.

Episode 409 – You wouldn’t hack a train?

Posted by Josh Bressers on January 01, 2024 12:00 AM

Josh and Kurt talk about how some hackers saved the day with a Polish train. We delve into a discussion about how we don’t really own anything anymore if you look around. There’s a great talk from the Blender Conference about this and how GPL makes a difference in the world of software ownership. It’s sort of a dire conversation, but not all hope is lost.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3285-8" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_409_You_wouldnt_hack_a_train_fixed.mp3?_=8" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_409_You_wouldnt_hack_a_train_fixed.mp3</audio>

Show Notes

Episode 408 – Does Kubernetes need long term support?

Posted by Josh Bressers on December 25, 2023 12:00 AM

Josh and Kurt talk about a story asking for a Kubernetes LTS. Should open source projects have LTS versions? What does LTS even mean? Why is maintaining software so hard? It’s a lively discussion all about the past, present, and future of open source LTS.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3280-9" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_408_Does_Kubernetes_need_long_term_support_fixed.mp3?_=9" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_408_Does_Kubernetes_need_long_term_support_fixed.mp3</audio>

Show Notes

Episode 407 – Should Santa use AI?

Posted by Josh Bressers on December 18, 2023 12:00 AM

It’s the 2023 Christmas Spectacular! Josh and Kurt talk about what would happen if Santa starts using AI to judge which children are naughty and nice. There’s some fun in this one, but it does get pretty real. While we tried to discuss Santa using AI, the reality is this sort of AI is coming for many of us. AI will be making decisions for all of us in the near future (if it isn’t already). While less fun than we had hoped for, it’s an important conversation.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3272-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_407_Should_Santa_use_AI.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_407_Should_Santa_use_AI.mp3</audio>

Show Notes

Episode 406 – The security of radio

Posted by Josh Bressers on December 11, 2023 12:00 AM

Josh and Kurt talk about a few security stories about radio. The TETRA:BURST attack on police radios, spoofing GPS for airplanes near Iran, and Apple including cellular radios in the macbooks. The common thread between all these stories is looking at the return on investment for security. Sometimes good enough security is fine, sometimes it’s not worth fixing certain security problems because the risk vs reward doesn’t work out.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3268-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_406_The_security_of_radio.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_406_The_security_of_radio.mp3</audio>

Show Notes

Episode 405 – Modding games isn’t cheating and security isn’t fair

Posted by Josh Bressers on December 04, 2023 12:00 AM

Josh and Kurt talk about Capcom claiming modding a game is akin to cheating. The arguments used are fundamentally one of equity vs equality. Humans love to focus on equality instead of equity when we deal with most problems. This is especially true in the world of security. Rather than doing something that has a net positive, we ignore the details and focus on doing something that feels “right”.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3263-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_405_Modding_games_isnt_cheating_and_security_isnt_fair.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_405_Modding_games_isnt_cheating_and_security_isnt_fair.mp3</audio>

Show Notes

recvfrom system call in python

Posted by Adam Young on November 27, 2023 07:21 PM

With a socket created, and a message sent, the next step in our networking journey is to receive data.

Note that I used this post to get the parameter right. Without using the ctypes pointer function I got an address error.

print("calling recvfrom")
recv_sockaddr_mctp = struct_sockaddr_mctp(AF_MCTP, 0, mctp_addr , 0, 0)
len = 2000;
rxbuf = create_string_buffer(len)
sock_addr_sz = c_int(sizeof(recv_sockaddr_mctp))
MSG_TRUNC = 0x20
rc = libc.recvfrom(sock, rxbuf, len, MSG_TRUNC, byref(recv_sockaddr_mctp), pointer(sock_addr_sz));
errno = get_errno_loc()[0]

if (rc < 0 ):
    print("rc = %d errno =  %d" % (rc, errno))
    exit(rc)

print(rxbuf.value)

From previous articles you might be wondering about these values.

AF_MCTP = 45
mctp_addr = struct_mctp_addr(0x32)

However, the real magic is the structures defined using ctypesgen. I recommend reading the previous article for the details.

While the previous two article are based on the code connect example that I adjusted and posted here, the recvfrom code is an additional call. The c code it is based on looks like this:

    addrlen = sizeof(addr);

    rc = recvfrom(sd, rxbuf, len, MSG_TRUNC,
                (struct sockaddr *)&addr, &addrlen);

Episode 403 – Does the government banning apps work?

Posted by Josh Bressers on November 27, 2023 12:00 AM

Josh and Kurt talk about the Canadian Government banning WeChat and Kaspersky. There’s a lot of weird little details in this conversation. It fundamentally comes down to a conversation about risk. It’s easy to spout nonsense about risk, but having an honest discussion about it is REALLY complicated. But the government plays by a very different set of rules.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3258-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_403_Does_the_government_banning_apps_work.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_403_Does_the_government_banning_apps_work.mp3</audio>

Show Notes

sendto system call from python

Posted by Adam Young on November 22, 2023 08:18 PM

Once we open a socket, we probably want to send and receive data across it.Here is the system call we need to make in order to send data as I wrote about in my last post:

c = sendto(sd, buf, sizeof(buf), 0,
                (struct sockaddr *)&addr, sizeof(addr));

Note the cast of the addr parameter. This is a structure with another structure embedded in it. I tried hand-jamming the structure, but the data sent across the system call interface was not what I expected. In order to make it work ,I uses a utility called ctypesgen with the header I separated out in my last post. Runing this:

ctypesgen ./spdmcli.h

generates a lot of code, much of which I don’t need. The part I do need looks like this:


__uint8_t = c_ubyte# /usr/include/bits/types.h: 38
__uint16_t = c_ushort# /usr/include/bits/types.h: 40
__uint32_t = c_uint# /usr/include/bits/types.h: 42
uint8_t = __uint8_t# /usr/include/bits/stdint-uintn.h: 24
uint16_t = __uint16_t# /usr/include/bits/stdint-uintn.h: 25
uint32_t = __uint32_t# /usr/include/bits/stdint-uintn.h: 26

# /root/spdmcli/spdmcli.h: 5
class struct_mctp_addr(Structure):
    pass

struct_mctp_addr.__slots__ = [
    's_addr',
]
struct_mctp_addr._fields_ = [
    ('s_addr', uint8_t),
]

# /root/spdmcli/spdmcli.h: 9
class struct_sockaddr_mctp(Structure):
    pass

struct_sockaddr_mctp.__slots__ = [
    'smctp_family',
    'smctp_network',
    'smctp_addr',
    'smctp_type',
    'smctp_tag',
]
struct_sockaddr_mctp._fields_ = [
    ('smctp_family', uint16_t),
    ('smctp_network', uint32_t),
    ('smctp_addr', struct_mctp_addr),
    ('smctp_type', uint8_t),
    ('smctp_tag', uint8_t),
]

# /root/spdmcli/spdmcli.h: 3
try:
    MCTP_TAG_OWNER = 0x08
except:
    pass

mctp_addr = struct_mctp_addr# /root/spdmcli/spdmcli.h: 5

sockaddr_mctp = struct_sockaddr_mctp# /root/spdmcli/spdmcli.h: 9

With those definition, the following code makes the system call with the parameter data in the right order:


mctp_addr = struct_mctp_addr(0x32) # /root/spdmcli/spdmcli.h: 16
sockaddr_mctp = struct_sockaddr_mctp(AF_MCTP, 1, mctp_addr , 5, 0x08)

p = create_string_buffer(b"Held") 
p[0] = 0x10 
p[1] = 0x82

sz = sizeof(sockaddr_mctp)
print("calling sendto")


rc = libc.sendto(sock, p, sizeof(p), 0, byref(sockaddr_mctp), sz) 
errno = get_errno_loc()[0]
print("rc = %d errno =  %d" % (rc, errno)   )

if (rc < 0 ):
    exit(rc)

print("OK")

With this Next step is to read the response.

Updated MCTP send code

Posted by Adam Young on November 22, 2023 04:26 PM

While the existing documentation is good, there are a couple things that have changed since it was originally written, and I had to make a couple minor adjustments to get it to work. Here’s the code to send a message. The receive part should work as originally published; what is important is the set of headers. I built and ran this on an AARCH64 platform running Fedora 38.

I split the code into a header and a .c file for reasons I will address in another article.

spdmcli.h

#include <stdint.h>

#define MCTP_TAG_OWNER 0x08

struct mctp_addr {
    uint8_t             s_addr;
};

struct sockaddr_mctp {
    uint16_t            smctp_family;
    uint32_t            smctp_network;
    struct mctp_addr    smctp_addr;
    uint8_t             smctp_type;
    uint8_t             smctp_tag;
}

I also coded this for spdm, not MCTP control messages. The difference is the value for addr.smctp_type

EDIT: I also added the recvfrom call to make this complete.

spdmcli.c

#include <linux/mctp.h>
#endif
#include <linux/if_link.h>
#include <linux/rtnetlink.h>

#include "stdio.h"
#include "spdmcli.h"

int main(void)
{
    struct sockaddr_mctp addr = { 0 };
    char buf[] = "hello, world!";
    int sd, rc;

    /* create the MCTP socket */
    sd = socket(AF_MCTP, SOCK_DGRAM, 0);
    if (sd < 0)
        err(EXIT_FAILURE, "socket() failed");

    /* populate the remote address information */
    addr.smctp_family = AF_MCTP;  /* we're using the MCTP family */
    addr.smctp_addr.s_addr = 0x32;   /* send to remote endpoint ID 32 */
    addr.smctp_type = 5;          /* encapsulated protocol type iSPDM = 5 */
    addr.smctp_tag = MCTP_TAG_OWNER; /* we own the tag, and so the kernel
                                        will allocate one for us */

    addr.smctp_network = 1 ;
    /* send the MCTP message */
    rc = sendto(sd, buf, sizeof(buf), 0,
                (struct sockaddr *)&addr, sizeof(addr));

    if (rc != sizeof(buf))
        err(EXIT_FAILURE, "sendto() failed");

   //EDIT: The following code recieves a message from the network and prints it to the console.
        if (rc < 0){
        err(EXIT_FAILURE, "recvfrom() failed");
    }

    printf("recv rc = %d\n",rc);        

    for (int i =0; i< rc; i++){
        printf("%x", rxbuf[i]); 

    }



    return EXIT_SUCCESS;
}

socket system call from python

Posted by Adam Young on November 21, 2023 08:37 PM

While the Python socket API is mature, it does not yet support MCTP. I thought I would thus try to make a call from python into native code. The first step is to create a socket. Here is my code to do that.

Note that this is not the entire C code needed to make network call, just the very first step.I did include the code to read errno if the call fails.

#!/usr/bin/python3
from ctypes import *
libc = CDLL("/lib64/libc.so.6")
AF_MCTP = 45
SOCK_DGRAM  = 2
rc = libc.socket (AF_MCTP, SOCK_DGRAM, 0)
#print("rc = %d " % rc)
get_errno_loc = libc.__errno_location
get_errno_loc.restype = POINTER(c_int)
errno = get_errno_loc()[0]
print("rc = %d errno =  %d" % (rc, errno)   )
print("OK")

Running this code on my machine shows success

# ./spdm.py 
rc = 3 errno =  0
OK

Episode 402 – The EU’s eIDAS regulation is a terrible idea

Posted by Josh Bressers on November 20, 2023 12:00 AM

Josh and Kurt talk about the new EU eIDAS regulation. This is a bill that will force web browsers to add root certificates based on law instead of technical merits, which is how it’s currently done. This is concerning for a number of reasons that we discuss on the show. This proposal is not a good idea.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3254-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_402_The_EUs_eIDAS_regulation_is_a_terrible_idea.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_402_The_EUs_eIDAS_regulation_is_a_terrible_idea.mp3</audio>

Show Notes

Refactoring in C: Introduce Dispatch Map

Posted by Adam Young on November 13, 2023 07:33 PM

There is a pretty common pattern in C coding that uses a Key, often an integer, to select a function to call. However, code may not start there, and there is a pretty common set of interim steps you might go to get there.

The growth is often like this:

If the logic for each case is similar and/or small, the switch statement may well be the final state. However, if the logic inside each of the case blocks gets too complex, then an common step that can be injected as soon as step 2 is to execute the refactoring of extract method except that we will call it extract function, we don’t have methods in C.

To give a concrete example, I am working with MCTP, a protocol where a message is delivered in a buffer. We take the payload of the buffer and select a specific offset to see the “type” of the message, and based on that type code, we need to perform a different operation. The Type code is the first byte of the payload, and it states what the higher level protocol is. In its current state of evolution, that can be one of three things: MCTP control messages, PLDM, or SPDM. Thus, the code evolution looks like this.

Handle the first case in the main method.

static void mctpserv_deliver(struct mbox_client * cl, void * data){
        struct mctp_pcc_packet * mpp;
        mpp  = (struct mctp_pcc_packet *)data;
        //do Simple MCTP stuff
        //send back status
}


Use an If statement to handle the error case

static void mctpserv_deliver(struct mbox_client * cl, void * data){
        struct port_handler mapping;
        struct mctp_pcc_packet * mpp;
        mpp  = (struct mctp_pcc_packet *)data;
        pr_info("%s signature = %x \n", __func__,
        (u32)mpp->pcc_header.signature);
        if (mpp->payload[0]  == MCTP_CONTROL){
                  //do Simple MCTP stuff
                  //send back success status  
        }else{
                  //send back error code
        }
 
}

Use an extended if/else clause to handle the second case

static void mctpserv_deliver(struct mbox_client * cl, void * data){
struct port_handler mapping;
struct mctp_pcc_packet * mpp;
mpp = (struct mctp_pcc_packet *)data;
pr_info(“%s signature = %x \n”, __func__,
(u32)mpp->pcc_header.signature);
if (mpp->payload[0] == MCTP_CONTROL_CODE){
//do Simple MCTP stuff
//send back success status
}else if((mpp->payload[0] == SPDM_CODE)) {
//do SPDM stuff
}else{
//send back error code
}
}

Use a switch statement to handle more than one case

static void mctpserv_deliver(struct mbox_client * cl, void * data){
        struct port_handler mapping;
        struct mctp_pcc_packet * mpp;
        mpp  = (struct mctp_pcc_packet *)data;
        pr_info("%s signature = %x \n", __func__,
        (u32)mpp->pcc_header.signature);
        switch (mpp->payload[0]){
             case MCTP_CONTROL_CODE: {
                  //do Simple MCTP stuff
                  //send back success status
             };  
             break;
             case SPDM_CODE: {
                  //do SPDM stuff        
              };
              break;
              default: 
                  //send back error code
        }
}

Extract function

void handle_mctp(struct mctp_pcc_packet * mpp){
//...
}

void handle_spdm(struct mctp_pcc_packet * mpp){
//...
}

void handle_pldm(struct mctp_pcc_packet * mpp){
//...
}


static void mctpserv_deliver(struct mbox_client * cl, void * data){
        struct port_handler mapping;
        struct mctp_pcc_packet * mpp;
        mpp  = (struct mctp_pcc_packet *)data;
        pr_info("%s signature = %x \n", __func__,
        (u32)mpp->pcc_header.signature);
        switch (mpp->payload[0]){
             case MCTP_CONTROL_CODE:  
               handle_mctp(mpp);
               break;
             case SPDM_CODE:
               handle_spdm(mpp);
               break;
            case PLDM_CODE:
               handle_pldm(mpp);
               break;
              default: 
                  //send back error code
        }
}

Note that when we extract the function, we use the same function signature. This is deliberate so we can use a function pointer in the next step without having to change the parameters passed to it. In order to define the function signature and the key used to select it, we put both inside a structure. for added type safety, use an enum to limit the values to the acceptable range.

enum MCTP_MSG_TYPE {
        MCTP_MSG_TYPE_CTRL = 0,
        MCTP_MSG_TYPE_PLDM = 1,
        MCTP_MSG_TYPE_SPDM = 5,
};
struct port_handler {
        enum MCTP_MSG_TYPE code;
        void (* handler )(struct mctp_pcc_packet * mpp);
};
struct port_handler handlers[]  = {

        {MCTP_MSG_TYPE_CTRL, handle_mctp },
        {MCTP_MSG_TYPE_PLDM, handle_pldm},
        {MCTP_MSG_TYPE_SPDM, handle_spdm}
};

One thing this example shows is why not to use the index of the array as the key; a sparse and non contiguous integer sequence means you would have a lot of wholes in that array. We need 0, 4, and 5 only.

Since our sequence is short, we can iterate through it using a linear search:

        for (int i = 0;  i <  sizeof(handlers)  / sizeof(struct port_handler )  ; i++){
                if (handlers[i].code == mpp-> payload[0]){
                        handlers[i].handler(mpp);
                        break;
                }
        }

For longer lists, it might be necessary to use a binary search. I am not going to show an example of that here, as I have not written it, and my example would certainly be buggy.

Handle a missing function

This example does not show how to handle a missing function. There are two ways I have done this: either set a boolean when the handler is called, or have the default case be an error handler. Here is the default case as a function.

void default_handler(struct mctp_pcc_packet * mpp){
        pr_info("%s unsupported protocol \n", __func__);
}
struct port_handler default_mapping = {
        MCTP_MSG_TYPE_MAX,
        default_handler,
};
static void mctpserv_deliver(struct mbox_client * cl, void * data){
        struct port_handler * mapping = &default_mapping;
        struct mctp_pcc_packet * mpp;

        pr_info("%s\n", __func__);

        mpp  = (struct mctp_pcc_packet *)data;
        pr_info("%s signature = %x \n", __func__,
        (u32)mpp->pcc_header.signature);
        pr_info("%s type code = %d \n", __func__, mpp-> payload[0] );


        for (int i = 0;  i <  sizeof(handlers)  / sizeof(struct port_handler )  ; i++){
                if (handlers[i].code == mpp-> payload[0]){
                        mapping = &handlers[i];
                        break;
                }
        }
        mapping->handler(mpp);
}

Episode 401 – Security skills shortage – We’ve tried nothing and the same thing keeps happening

Posted by Josh Bressers on November 13, 2023 12:00 AM

Josh and Kurt talk about security skills shortage. We start out on the topic of cybersecurity skills and weave our way around a number of human related problems in this space. The world of tech has a lot of weird problems and there’s not a lot of movement to fix many of them. Tech is weird and hard, and with the almost complete lack of regulation creates some of these challenges. In the world of security we need a better talent pipeline, but that takes actual efforts, not just complaining on the internet.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3250-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_401_Security_skills_shortage_Weve_tried_nothing_and_the_same_thing_keeps_happening.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_401_Security_skills_shortage_Weve_tried_nothing_and_the_same_thing_keeps_happening.mp3</audio>

Show Notes

Episode 400 – When can the government hack a victim?

Posted by Josh Bressers on November 06, 2023 12:00 AM

Josh and Kurt talk about a proposed Dutch proposal that would allow the intelligence services to hack victims of adversaries they are in the process of infiltrating. The purpose of this discussion isn’t to focus on the Dutch specifically, but rather to discuss the larger topic of government oversight. These are all very new concepts and nobody knows how things should work.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3246-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_400_When_can_the_government_hack_a_victim.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_400_When_can_the_government_hack_a_victim.mp3</audio>

Show Notes

Round Trip with MCTP over PCC

Posted by Adam Young on November 02, 2023 07:17 PM

The future Ampere System-on-a-chip that is the basis for my work has a couple of processors that are for providing system wide services, not for end users to run things on directly. One of these is called the Management Processor, or Mpro. We have to talk to one of these services from the operating system using the Management Control Transport Protocol, or MCTP, over a Platform Communication Channel (PCC).

I just sent ran a user-land program that sends a message via a socket into the operating system, via PCC, to the MPro, and got a response back.

It took a while for it to sink in. And then I raised my hands in the air and proclaimed in my Best Dr. Frankenstein voice,

“It’s Alive!”


There were so many lessons I had to learn to get this this point. Here are a short list:

  1. How to implement a Linux Kernel network device driver
  2. How to register with the Linux Kernel to get an Advanced Configuration and Power Interface (ACPI) based device from data in the Differentiated System Description Table (DSDT).
  3. How to convert physical memory offsets to virtual
  4. How to read and write data from device memory
  5. How to lookup data in the ACPI tables (a work around for a mechanism not yet written)
  6. How to work with our firmware team to get their view of the debug data
  7. How to build a firmware image and deploy it to one of our lab machines
  8. How to build and run a unit test against mock objects inside the Linux Kernel
  9. How to read and implement the MCTP and related level protocol specs.

I work with really smart people. I would probably have been able to do this all myself…in another 15 years. The amount of time saved by working with the members of my team is probably longer than the life of the product I am working on.

Someone once said, “If you are the smartest person in the room, you are probably in the wrong room.” I suspect that I am absolutely in the right room for me.

The code is by no means done. In some ways, you might say that the real work begins now: getting it production ready, However I have always used the principal of “build from success” when working in software. First get something working, then make incremental improvements while keeping it working. This is my first real success and it feels good.

Episode 399 – Curl, Security, and Daniel Stenberg

Posted by Josh Bressers on October 30, 2023 12:00 AM

Josh and Kurt talk to Daniel Stenberg about curl. Daniel is the creator of curl, we chat with him about the security of curl. Daniel tells us how curl is kept secure, we learn about some of the historical reasons curl works the way it does. We hear the story about the curl CVE situation firsthand. We also touch on the importance of curating the community of a popular open source project.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3241-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_399_Curl_Security_and_Daniel_Stenberg.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_399_Curl_Security_and_Daniel_Stenberg.mp3</audio>

Show Notes

Episode 398 – Is only 11% of open source maintained?

Posted by Josh Bressers on October 23, 2023 12:00 AM

Josh and Kurt talk about Sonatype’s 9th Annual State of the Software Supply Chain. There’s a ton of data in the report, but the thing we want to talk about is the statistic that only 11% of open source is actually being maintained. Do we think that’s true? Does it really matter?

<audio class="wp-audio-shortcode" controls="controls" id="audio-3236-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_398_Is_only_11_of_open_source_mainted.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_398_Is_only_11_of_open_source_mainted.mp3</audio>

Show Notes

No Negative Access Rules

Posted by Adam Young on October 21, 2023 10:07 PM

If you don’t want someone to be able to delete the database, do not give them authority to delete the database.

Azure recently announced that they were implementing Negative access rules. A rule of this nature is such that you/ can say “User U cannot perform action A on resource R.”

This is an anti-pattern. It is a panic response to breaches caused by principals (users or agents ) that have far more power than they should have to perform operations than they need. What is the alternative?

Create a agents with minimal access to get done exactly what they need an no more.

Lets break this on down. I am going to use a web application to explain what this should look like. This application takes orders on line and send them to a back-end processing system to fulfill. As such, there are roughly four agents for different parts of the overall system.

  • The Web server
  • The Web servers Database
  • The messaging broker
  • The back-end fulfillment system.

Ulysses is the end user. Ulysses wants to buy a thing. Ulysses opens his browser and clicks through the pages. We’ll assume that the web-server is not running as root on the remote server, as that would be bad and we’ve all grown beyond that point. It is running as, say, the STORE user. This user can render pages to send back to Ulysses, and can query the database to get categories, products, SKUs, and few more things. For write access, this user can write to the order database, and can write order messages to the message queuing system. The STORE user can also read from the order update queue to change the order management database, although this is likely done by a different agent in practice.

OK, I think you can see how this same kind of pattern would be implemented by the order fulfillment system. Lets go back to our cloud provider and discuss a little further.

Odette is our owner. She is the one that pays the Cloud provider to set up her store, to sell things. Odette has contracted to Carlita to modify her web application to customize it for her needs. Dabney is her database administrator. In addition, she uses a service from her cloud provider to set up the application in the first place.

Which of these user should have authority to delete the database? None, obviously. But how does the database get created in the first place? Automated processes set up by the cloud provider. Modifications performed on the database should happen via git, with code review required by at least one other person to accept a merge request. This merge request then goes into a staging branch, staged, and again requires manual approval to be pushed to the live server.

THE actual pushing of changes from one stage to another are performed by agents with only the ability to perform the operations they need. Create and drop tables are handled by the database management agent. And yes, this one, if compromised, could destroy the database. However, another agent performs backups prior to any operations that alter the tables. A deleted table can be created by rolling aback to a previous version, acknowledging that all data that came in post corruption will be lost.

It ain’t easy. It ain’t simple, and it ain’t free. But it is all necessary.

So why are negative rules such a big deal? Surely adding an explicit deny rule on top of all the explicit allow rules provides an added layer of security? There are a few problems with this approach, First, it only actively denies actions you have actually foreseen as problematic. For instance, it would not catch that the Store user could delete the order export queue, or that the order update agent could alter the order update table to a format that was broken. You want to deny everything by default. Then, to test to see if a user can perform a specific action, you can query the role assignments to see if a user has the dangerous permission. If they do, you probably need to create a new, more fine grained role, that has only the permissions required.

A good example of a system that works this way is SELinux. IN an SELinux hardened system, everything is forbidden until explicitly allowed. The critical tool that makes SELinux workable is permissive mode. When you run a NON_PRODUCTION system in permissive mode, you see what would have been denied by the existing set of rules, and you make new rules that would allow those actions. Then you go back into enforcing mode and run, and make sure you can get through the required workflow with all required actions allowed and all forbidden actions denied. This workflow would replace the explicit Deny rules above.

Deny rules add an additional complication. Now you need to explicitly order your rules. First, you have the default Rule of Deny All. Then you have the explicit allow rules, and finally the deny rules. But what happens if someone comes by later and wants an exception to the deny rule. Maybe this account should not be able to delete production databases, but staging ones are just fine? If your blanket deny stops them from deleting all databases, you might be stuck.

And that is what the Deny rules should be: unit tests that show an action is denied. Not an actual rule itself. Because all actions should be denied by default, and if you can accidentally assign one action, you probably accidentally allowed a bunch of other actions as well. So, do not make Deny actions part of your enforcement rule set. Make them part of your explicit tests after the fact.

Deny rules have been a part of many access control systems over the years. This is not the first time this discussion has come up, nor will it be the last. This is one of those “must have” features that keep popping up. Its an anti pattern and should be avoided. The rational developer can only say no so many times before someone does an end run around them and someone puts negative rules in the system.

Attestation in a Nutshell

Posted by Adam Young on October 21, 2023 02:32 PM

One of my current engineering efforts is in support of the concept of hardware attestation. What is that? Here’s my attempt at a summary:

Attestation is a way of showing something is true. In this case, it is proving that the software you are talking to is from a trusted vendor. In my case, that software is the Firmware for the System-on-A-Chip. While there are many levels of Attestation, they all resolve down to the lowest level software. It doesn’t matter if the Operating System is good if the Firmware is bad, there is the potential for a violation. This is no guarantee that there is not a violation. Attestation is necessary-but-not-sufficient.

How do we attest? Well, we have to talk to a server. There are two different types of servers I have been exposed to in my current effort: BMC and Operating System. They do roughly the same thing. Some external program makes a connection to either the BMC or the OS, and and makes an attestation request. “Show me the firmware you are running and a cryptographic signature for it.” Basically, I am back in the world of X509 certificates. Although attestation does not need to be done with X509, it needs all the stuff from X509 and so it is easiest to explain in terms of X509.

The building blocks:

The main building block of most computer security is the concept of asymmetric cryptography. This means that you have a computer algorithm that can encry0pt and decrypt messages. The keys used by this algorithm are related to each other but different from each other. One is going to be labeled the public key. The other is the private key. Which is which is arbitrary, but once you decide, you need to treat them consistently. If you use the public key to encrypt a message, you can only use the private key to decrypt it, But if you use the private key to encrypt a message, you can only use the public key to decrypt it. There are many ways that these are used, but I am going to focus on one of the; signatures. However, before we can explain signatures, we need one more concept: hashes.

A cryptographic hash algorithms takes a long document and produces a short string that represents that document. What is special about cryptographic hashes is that a very small change in the docuemtn produces a different hash. If you change a period to a comma, you get a different hash.

I can take the text above, starting with the phrase “Attestation is a way…” up to the phrase ” you get a Different Hash” and put and put it in a text document. I will also add an addtional line and put a period on it. I can use the program sha256sum to product the hash like this:

sha256sum attest.txt 
396f4edd98ddf09d44a2842e9495db25b7e7b5a0b5a747a4fd29b8e36c5abfab  attest.txt

However, if I change the final character from a period to a comma,

diff attest.txt attest2.txt 
10c10
< .
---
> ,

I get this:

sha256sum attest2.txt
9282e247e2b21a49731b2a631ed2fc2afb3184fc5908ee893111ad6cfb142f9e attest2.txt

A cryptographic signature for a document takes a sha256 hash and encrypts it with a private key. Now If someone wants to confirm a document, they 1. Use the public key to decrypt the hash and 2, hash the document themselves to see that the hashes match.

Attestation is based on requesting a signature for the firmware running on a system. The public key used to validate that signature comes from a cryptographic certificate (that is where X509 comes in) so you can establish a chain of trust. X509 is a fairly huge area, but the only part of it necessary to understand here is that one public key can be used to sign a document containing another public key…and so on in chains. This is how your computer set up an https session to read this blog, and also used in many of the algorithms used to identify yourself on the internet.

OK, that is a pretty big nutshell. Maybe a coconut. But I think that is a succinct as I can make it. This skips a lot of the context.

Hello To Stephen Smoogen

Posted by Adam Young on October 16, 2023 10:53 PM

This post is a novelty post merely to say hello to a friend of mine that gave me a shout out else-where.

Hi Stephen.

Building a Fedora Based Linux Kernel

Posted by Adam Young on October 16, 2023 08:06 PM

We have a few different ways we build a Kernel for internal consumption. One is very minimal, to be used when space is at a premium. Another is very closely based on the Fedora configuration to be used as a replacement Kernel for a Fedora install. While we do provide our team with RPMs to install, development often requires building from source. I’ve done this (and forgotten steps) enough times to want to have a quick reference. The following should work on a recent Fedora install.

yum groupinstall "Development Tools"
yum install dwarves openssl grubby
git clone git@$(GITSERVER):$(LINUX_REPO).git
cd linux
cp $( KERNEL_CONFIG_SOURCE) ./.config
make olddefconfig
make -j `nproc`  && make -j `nproc` modules && make -j `nproc` modules_install && make install
grubby --set-default-index=0
reboot

Episode 397 – The curl and glibc vulnerabilities

Posted by Josh Bressers on October 16, 2023 12:00 AM

Josh and Kurt talk about a curl and glibc bug. The bugs themselves aren’t super interesting, but there are other conversations around the bugs that are interesting. Why don’t we just rewrite everything in Rust? Why can’t we just train developers to stop writing insecure code. How can AI solve this problem? It’s a marvelous conversation that ends on the very basic idea: we already have the security the market demands. Unless we change that demand, security won’t change.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3232-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_397_The_curl_and_glibc_vulnerabilities.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_397_The_curl_and_glibc_vulnerabilities.mp3</audio>

Show Notes

Sausage Factory: Fedora ELN Rebuild Strategy

Posted by Stephen Gallagher on October 13, 2023 01:34 PM

The Rebuild Algorithm (2023 Edition)

Slow and Steady Wins the Race

The Fedora ELN SIG maintains a tool called ELNBuildSync1 (or EBS) which is responsible for monitoring traffic on the Fedora Messaging Bus and listening for Koji tagging events. When a package is tagged into Rawhide (meaning it has passed Fedora QA Gating and is headed to the official repositories), EBS checks whether it’s on the list of packages targeted for Fedora ELN or ELN Extras and enqueues it for the next batch of builds.

A batch begins when there are one or more enqueued builds and at least five wallclock seconds have passed since a build has been enqueued. This allows EBS to capture events such as a complete side-tag being merged into Rawhide at once; it will always rebuild those together in a batch. Once a batch begins, all other messages are enqueued for the following batch. When the current batch is complete, a new batch will begin.

The first thing that is done when processing a batch is to create a new side-tag derived from the ELN buildroot. Into this new target, EBS will tag most of the Rawhide builds. It will then wait until Koji has regenerated the buildroot for the batch tag before triggering the rebuild of the batched packages. This strategy avoids most of the ordering issues (particularly bootstrap loops) inherent in rebuilding a side-tag, because we can rely on the Rawhide builds having already succeeded.

Once the rebuild is ready to begin, EBS interrogates Koji for the original git commit used to build each Rawhide package (in case git has seen subsequent, unbuilt changes). The builds are then triggered in the side tag concurrently. EBS monitors these builds for completion. If one or more builds in a batch fails, EBS will re-queue it for another rebuild attempt. This repeats until the same set of failures occurs twice in a row. Once all of the rebuild attempts have concluded, EBS tags all successful builds back to ELN and removes the side tag. Then it moves on to preparing another batch, if there are packages waiting.

History

In its first incarnation, ELNBuildSync (at the time known as DistroBuildSync) was very simplistic. It listened for tag events on Rawhide, checked them against its list and then triggered a build in the ELN target. Very quickly, the ELN SIG realized that this had significant limitations, particularly in the case of packages building in side-tags (which was becoming more common as the era of on-demand side-tags began). One of the main benefits of side-tags is the ability to rebuild packages that depend on one another in the proper order; this was lost in the BuildSync process and many times builds were happening out of order, resulting in packages with the same NVR as Rawhide but incorrectly built against older versions of their dependencies.

Initially, the ELN SIG tried to design a way to exactly mirror the build process in the side-tags, but that resulted in its own new set of problems. First of all, it would be very slow; the only way to guarantee that side-tags are built against the same version of their dependencies as the Rawhide version would be to perform all of those builds serially. Secondly, even determining the order of operations in a side-tag after it already happened turned out to be prohibitively difficult.

Instead, the ELN SIG recognized that the Fedora Rawhide packagers had already done the hardest part. Instead of trying to replicate their work in an overly-complicated manner, instead the tool would just take advantage of the existing builds. Now, prior to triggering a build for ELN, the tool would first tag the current Rawhide builds into ELN and wait for them to be added to the Koji buildroot. This solved about 90% of the problems in a generic manner without engineering an excessively complicated side-tag approach. Naturally, it wasn’t a perfect solution, but it got a lot further. (See below for “Why are some package not tagged into the batch side-tag?” for more details.

The most recent modification to this strategy came about as CentOS Stream 10 started to come into the picture. With the intent to bootstrap CS 10 initially from ELN, tagging Rawhide packages to the ELN tag suddenly became a problem, as CS 10 needs to use that tag event as its trigger. The solution here was not to tag Rawhide builds into Fedora ELN directly, but instead to create a new ELN side-tag target where we could tag them, build the ELN packages there and then tag the successful builds into ELN. As a result, CS 10 builds are only triggered on ELN successes.

Frequently Asked Questions

Why does it sometimes take a long time for my package to be rebuilt?

Not all batches are created equal. Sometimes, there will be an ongoing batch with one or more packages whose build takes a very long time to complete. (e.g. gcc, firefox, chromium). This can lead to up to a day’s lag in even getting enqueued. Even if your package was part of the same batch, it will still wait for all packages in the batch to complete before the tag occurs.

Why do batches not run in parallel?

Simply put, until the previous batch is complete, there’s no way to know if a further batch relies on one or more changes from the previous batch. This is a problem we’re hoping might have a solution down the line, if it becomes possible to create “nested” side-tags (side-tags derived from another side-tag instead of a base tag). Today however, serialization is the only safe approach.

Why are some packages not tagged into the batch side-tag?

Some packages have known incompatibilities, such as libllvm and OCAML. The libraries produced in the ELN build and Rawhide build are API or ABI incompatible and therefore cannot be tagged in safely. We have to rely on the previous ELN version of the build in the buildroot.

Why do you not tag successes back into ELN immediately?

Not all ELN packages are built by the auto-rebuilder. Several are maintained individually for various reasons (the kernel, ceph, crypto-policies, etc.). We don’t want to tag a partial batch in out of concern that this could break these other builds.

  1. Technically, the repository is called DistroBuildSync because originally it was meant to serve multiple purposes of rebuilding ELN from Rawhide and also syncing builds for CentOS Stream and RHEL. However, the latter two ended up forking off very significantly, so we renamed ours to ELNBuildSync to reduce confusion between them. It unfortunately retains the old name for the repo at the moment due to deployment-related reasons. ↩

Querying the PCCT in Python

Posted by Adam Young on October 12, 2023 03:16 PM

The Platform Communication Channel Table contains information used to send messages in a shared memory buffer between the Operating System and other subsystems on the platform. Typically, the Channel has an interrupt defined that is used to tell the other subsystem that there is new data available.

Recently, I’ve been working with a couple entries that are of a newer type. In addition to the shared memory region and the interrupt values, the PCCT entries for type 3 and type 4 channels also have a series of registers. Where before the PCCT entries were normalized, now they are hierarchical. This makes them a little harder to scan with the human eye to confirm that the proper values have been recorded and read.

To simplify development, I build a simple script.

#!/usr/bin/python3

import json

import pdb

pcct = dict()

def to_json():
        current = pcct
        parent = pcct
        with open("pcct.dsl", "r") as f:
                for line in f:
                        if line.startswith("["):
                                index = line.find("]")
                                data = line[index +1:]  
                                index = data.find(":")
                                key = data[0:index].strip()
                                value = data[index+1:].strip()
                                
                                if (key == 'Subtable Type'):
                                        #subcount = 1
                                        parent = dict()
                                        subtables = pcct.get('subtables',[])
                                        subtables.append(parent)
                                        current = parent
                                        pcct['subtables'] = subtables
                                elif value == "[Generic Address Structure]": 
                                        current = dict()
                                        parent[key] = current
                                current[key] = value


def report_on_pcct():
        for sub in pcct['subtables']:
                sub_type = sub['Subtable Type']
                if sub_type.startswith('03') or sub_type.startswith('04'):
                        print(sub_type)
                        print( "  %29s       = %s" % ( "Base Address", sub.get('Base Address',"unset")))
                        print( "  %29s       = %s" % ( "Platform Interrupt ", sub.get('Platform Interrupt',"unset")))
                        for key, value in sub.items():
                                if isinstance(value, dict):
                                        if value.get(key, '') == "[Generic Address Structure]":
                                                print( "  %29s Address      = %s" % ( key, value.get('Address',"unset")))
                                                for k2, v2 in value.items():
                                                        if k2.endswith('Mask'):
                                                                print( "  %29s              = %s" % ( k2, v2))

to_json()                               
print(json.dumps(pcct, indent =2))
report_on_pcct()

Even in a simple script like this, I tend to iterate. My origianl intention was to merely convert the PCCT to JSON and then use jq to query it. Halfway through I realized it was easier to do the query in python. So, while I am still outputing the whole table in JSON, I display the values I actually care about underneath it.

Here is some of the output from a sample run:

03 [Extended PCC Master Subspace]
                   Base Address       = 00004000000D4004
            Platform Interrupt        = 0000002E
              Doorbell Register Address      = 00004000006B6010
                  Preserve Mask              = 0000000000000000
                     Write Mask              = 0000000000000000
          Platform ACK Register Address      = 00004000006B6020
              ACK Preserve Mask              = 0000000000000000
                   ACK Set Mask              = 0000000000000001
      Command Complete Register Address      = 00004000000D4000
    Command Complete Check Mask              = 0000000000000001
        Command Update Register Address      = 00004000000D4000
   Command Update Preserve Mask              = 0000000000FF0004
        Command Update Set Mask              = 0000000000000000
          Error Status Register Address      = 00004000000D4000
              Error Status Mask              = 0000000000000004

I made an effort at lining up the output values. Aside from neatness, it makes it easier to scan down the column.

Writing this allowed us to zoom in on the fact that the preserve and write masks were both 0. This was quickly confirmed to be correct. This is not the final set of values for this table, just an interim copy that we checked.

This script is a good example of Data munging. The idea is that it is a four stage process: read, convert to a standard form, query. The standard internal form means you can mix and match on the reading and the query portions with other code should you with to do so.

Episode 396 – CLAs are bad, Mkay?

Posted by Josh Bressers on October 09, 2023 12:00 AM

Josh and Kurt talk about contributor license agreements (CLAs). CLAs used to be seen as a necessary evil, but they’re almost certainly bad now. We’re seeing CLAs being abused, it’s clear now anything controlled by a CLA won’t be open source forever.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3228-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_396_CLAs_are_bad_Mkay.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_396_CLAs_are_bad_Mkay.mp3</audio>

Show Notes

Perdido Explained

Posted by Adam Young on October 04, 2023 12:56 PM

I know where most of the inspirations for the details of this story come from. Here they are, with my thoughts on what I would do if I were to revise the story. Sorry if I explain some things that are obvious, but not everyone has the same background.

Perdido means “lost” in Spanish. It is the title of an old Jazz tune. Its actually a happy tune…that gets “lost” in that it endlessly repeats. My use of the title was meant to be darker.

The opening line is a play on the fact that my name is Adam.

I think the Desire character was an amalgam of the crushes from Highschool and before. They fit the description, as did the my crush from Plebe year. I kept the word Gypsy from the original story as that is how it was published. I had no concept that the term was derogatory. I feel like the narrator of this story, set in the eighties in my head, would not have known to use the word Rrom or Romani. I might say Balkan in a revised version, or specifically made her Romanian…and probably give her a Romani name. I might give my hero a couple of other girls in his history to reinforce the fear of intimacy and to justify his use of the term “The Rest.”

Orpheus was a musician in Greek mythology. His love, Euridice, dies and goes to Hades. Orpheus follows her there to get her out. However, as they are walking out of Hades realm, he defies the dictate of the lord of the underworld and looks back. He sees the silent shade of Euridice return back to the land of the dead. A modern retelling of it is in the Move “Orfeo Negro.” The title song is a Jazz standard Bossa Nova that I have played many times. Both references are deliberate, and apropos for an underground Jazz Club.

The dropping out of a physics program was inspired by Robert Pirsig of Zen and the Art of Motorcycle maintenance. He too joins the Army. The Jazz described here borrows a lot from that book and from Zen and the Art of Archery, especially in the ending sequence of the horn assembling itself and the music playing the musician.

Rachael is because I wanted a Jewish name. It might also have been inspired by the Rachael character that works with Conner MacCleod in the first (and only true) Highlander movie. Cullens, instead of Collins, was because I wanted something more Irish than English. Rachael is 20 or 21 years old. Their relationship had not moved to romantic by the time the action takes place. Both characters are more damaged than the real people that inspired them. If I were to revise, I might even make this an explicitly enumerated number of dates…like three. Enough so that he’s hooked and will take some action, but also enough that he is unsure if she really likes him. I might make it explicit that they haven’t gotten physical as I don’t want him to have too much information. And I didn’t want her to be comfortable with touching after her recent abuse.

Joe Kent is probably based on the Dale Turner character that Dexter Gordon played in “Round Midnight.” Francis befriends an alcoholic Dale. Dale is based on Dexter, himself a Jazz Giant, and on Lester Young, one of the first great tenor sax players. Lester invented many of the terms from Jazz, like Bread for money. In the movie, Francis and helps him get sober and playing again. The real life story is fairly similar, but instead of a tenor Sax Player, the real life Francis Paudras befriended the piano player Bud Powell. The name Joe is probably inspired by Joe Henderson, but its also just a good old sounding name. The name Kent is an allusion to my Uncle Ben, who went by many names when playing music (changing often for tax purposes). One of them was Kenny Benton. Uncle Ben got me started on Saxophone. Joe is probably also inspired by George Garzone. I took lessons from him during Highschool. He taught me Jazz, and he taught me how to think. He never said any of the things in this story, but they are not too far out for him. He’s known as the Yogi Berra of the Berklee School of Music.

The feeling of guilt over feeling happy was based on my reaction to my Grandmother’s death. At some point, I got frustrated about going to the funeral, I think. it was a long time ago and I was young. I then felt guilty for feeling frustrated.

Bill as the bartender was not my brother Bill, but rather a play on the song Piano man. Instead of John at the Bar, I put Bill there. The irony is that my brother Bill would become a Bartender a couple decades later.

The city it 2/3s New York and 1/3 Boston. The college is an amalgam of Brown, Tufts, and Faber College from Animal House.

The lake house is definitely supposed to be in The lakes region of New Hampshire. The house is mildly inspired by my folks house in New Hampshire, although it is laid out nothing like it, and there really wasn’t a back door. Also, we would never lock the doors of a vacation house while we were in it, but Aussie did, again showing he knows there is something wrong about the situation. Maybe the brother from the fraternity would have tried to call him, but he probably wouldn’t have the number. He might have called the police, but he probably was too freaked out and just hid in the house instead.

I have long been a fan of Spenser, both from the TV shows and from the Novels. I had been reading a bunch of the novels around the time I wrote this, and I took a lot of inspiration from them. I hope I didn’t rip them off too badly.

I don’t want to say too much about the inspiration for the attack. Suffice to say something very different and very similar happened to someone I was close to back in high school. It messed me up and sat there for a long time. That was probably the nucleus of this story. But she was not Rachael. And, while history does not repeat itself, it sometimes rhymes, and my description here reflects closely on other attacks I know of on other friends of mine that I have learned about after I wrote the story.

I think I have a bit of a hero complex. A desire to be a white knight, upon a fire-y steed. That is why I went to West Point. But I’m no Paladin. I’m a nerdy Jewish boy from the burbs. That plays saxophone.

When I went to Spain in 1986 or so, I read a comic book. It had several short comics. One was called ‘Juan, el Saxophonista de jusiticia” or Juan the saxophonist of justice. A captured woman is tied up by the villain. Juan (dressed as Zorro) swings in through the window. The villain is scared. Juan whips out his saxophone and starts wailing out a tune. The villain, no longer scared, hits him on the head. The final scene shows a recovering Juan with a friend remonstrating him, “Te he dicho. La Saxophone O la Justicia.” which translates to “I’ve told you. The Saxophone OR the the Justice.” Pretty sure the Adam in this story was actually Juan. He’s 26 years old.

The plot holes I would plug if I were to edit this are the fact that our narrator magically finds out where Kim lives, and the fact that they don’t actually teach privates to choke people to death. But what I’ve learned since then is the Buck Sargent that live off post may have junior enlisted over on weekends to drink and teach them martial arts. Privates also are not supposed to have fire arms in their barracks, but they could keep them in the arms room, and sign them out to take them to a range. But they are more likely to stash them at the Buck Sargent’s house, and there are very likely to be gun ranges in the vicinity of most Army posts. There certainly was in Hawaii. I’m sure there are others. It should feel mostly realistic that our untrained narrator would be able to solve this mystery.

I’d remove the charcoal rubbing. I like the interview with the former land lady, but I’d find a less silly way to work that in, probably by having a bunch of letters forwarded from the old address. I’d clean up her language, make her more real and less of a caricature. I think she might be inspired by some characters out of Herman Hesse novels. I’d keep the spectacles.

Aussie and the fraternity brother were as generic as I could make them. I wanted to mask the antagonist as long as I could, hence the nickname. Jason Peters is, I think, pulling in two names of Billy’s friends, but I liked those kids, so I don’t want to vilify them. I really just wanted as bland a name as possible. I don’t love the monologue that explains what happened, but I wanted to move the story as fast as possible. I possibly could drag that out, or have the narrator deduce what happened by some torn clothes etc. I do think that the not-eating part is important and I would keep that. I wanted the antagonist to be somewhat aware that he had done something very bad.

The fact that out narrator is a tanker shows that I had not yet chosen to go Infantry. That didn’t happened until the following summer, after Drill Cadet Leader Training with an Infantry Basic Training company at Fort Benning. But I knew I was probably going to have to go Combat Arms, and tanks seemed like a smart move, especially after Desert Storm.

Time was stress at West Point. Minute callers would announce how many minutes to formation. Being a minute caller meant being an open target for the upperclassmen. Being in formation meant being a target for upperclassmen. We had limited time to get between classes. Being late meant punishment. Loss of free time and more inspections. Weekends away were explosively fun, but we had to be back by accountability formation 1930 hours on Sunday night. Hence the clock to voice his frustration.

I could take the train down to NYC from West Point, provided I could get a ride across the river to the Garrison or Croton Harmon stations. I didn’t have a car at the time, and I figured a poor Jazz musician in the city wouldn’t have one either. The train does not run up to the lakes region anymore, but it did for a long time. The tracks are still there, and I have cross country skiied on them many times.

I am surprised myself by the amount of times I mentioned temperature or used it as a metaphor. I suspect it was the gloom period at West Point (January Through Spring) that inspired that. I was cold a lot. But the terms are used a lot in Jazz. Cool was Miles Davis. Hot Jazz was Louis Armstrong.

The closing is pure Humphrey Bogart. Or Mike Hammer. I probably couldn’t get away with playing Harlem Nocturn over the closing credits, but that is what I heard in my head.

Perdido

Posted by Adam Young on October 03, 2023 07:51 PM

Written By Adam Young.

This is a short story I wrote my Sophomore year at West Point. It was originally published in “The Circle in the Spiral” the one and only edition of the West Point literary magazine, published in early 1991. Apologies for in anachronisms. More on that later

<figure class="wp-block-image size-large">Perdido<figcaption class="wp-element-caption">Title in the Original publishing</figcaption></figure> <figure class="wp-block-image size-full">Not sure if this was meant to go with my story, but it appeared on the facing page.<figcaption class="wp-element-caption">Girl Wearing a Sailors Hat. Cannot read the signature</figcaption></figure>

Someone told me once that a woman would be my downfall. I know that my life would have been a lot less…interesting if I had never met Desiré. She was an artist and a free spirit. Gypsy black curly hair and pale white skin, large brown eyes, and energy. And I thought I loved her. But I moved too slowly, and soon her meteoric existence took her shooting out of my life.

The misery of losing her came across in my music. I had a steady gig playing sax in a combo at Orpheus, a bar in the city that was frequented by people on the fringes of society. My music seemed to attract those who felt as lost as I did.

Tuesday night is not a particularly hot night I the city, and I was feeling down. Living on music feeds the soul, but starves the body. I almost didn’t go to the gig that night, but I saw a ghost of my mentor in the mirror, looking over my shoulder. The need to play, to breathe music, swept me out the door of my one room apartment and onto the subway. The first snow of the year was just starting as I got off the train. Two blocks down was the club.

I guess the colleges had just finished up exams, for as we started up the first set, a group of ten students came in to the bar; standing room only. I put everything I had into the music. After the second set, I was drained. All the college kids were talking with each other, drinking, and doing everything except listing to the music. Except one. Her eyes were pale blue, like a lake with the faintest touch of frost. Her blonde hair was pulled back into a loose pony tail. She wore jeans the same pale blue as her eyes, a loose sweater, and low, water stained , black suede boots. She had a haunted look that reminded me of the old black white picture I had seen of Indians in the eighteen-hundreds.

She came in often after that. Usually with a group. A couple time I had thought about going up to talk with her, but I really couldn’t deal with it. Not yet. One night the group she was with decided to leave in the middle of a set. I watched her as she wavered and finally decided to stay. Alone. At the end of the night there was just the band, the bartender, the manager, and her. I walked up to her table. “It’s dangerous to walk alone this late at night.”

“You play like your world has fallen apart.” She had a low, husky voice that scraped my heart. “My name is Rachael.”

We walked along the harbor, not touching, neither of us having any place to go. We were silent for a long time. Inside, I was in tension. Remember Desiree. She seems lost. She’s just another girl going after a musician. She is beautiful. She’ll hurt me like The Rest. She turned to me, the reflection of the city making her eyes glow. She said, “Before my friends convinced me to come out, I had never really listened to Jazz before. I don’t even really know that much about the music.”

I didn’t trust myself to speak. Each word she spoke twisted like like a knife in the chest. I wanted to run. I wanted to hold her. We walked on in silence.

<figure class="wp-block-image size-large">"Living on music feeds the soul but starves the body."</figure>

“Is there someone special in your life?” She asked a couple of minutes later.

I could hear my pulse pounding in my ears. I shook my head. “You?” I asked.

She turned away for a moment. Her face was hidden by a shadow. She shook her head ever so slightly. “Not anymore.”

“What…?”

She cut me off with a shake of her head.

We stopped at a doughnut shop and got breakfast. I watched her as she played with her food.

“What are you studying in school?”

“I want to be a Doctor. Right now I am a Nurses Aide.”

“What are you doing over the vacation?” I asked as Gene Kruppa played “Sing Sing Sing” on my eardrums.

“I have a job at a doctors office downtown. I’ll be working there.” Her eyes drew me in.

She worked days and I nights. We saw each other for a few hours in the evening between when her work was done and mine started. We would meet for dinner at each other’s apartments, (hers, usually since mine was in a dangerous part of town). Each time I promised myself I would end it. I was not going to get involved again.

One night she was supposed to come over and she never showed. I called her house and there was no answer. I called her office. The receptionist said she had been picked up by a main in a black Pickup. I left the number at “Orpheus”

Kicking myself for getting involved again, cursing all woman, I got drunk and went to the gig. I played one set and left when I finally accepted that fact that she wasn’t going to call. I wandered all over the city. Sitting on a dock on a look-out over the harbor, I looked back over my life.

Long ago I realized that the world didn’t need me to save it. I also realized that I wasn’t happy studying physics at the university. Like a cartoon character who has the bridge cut out from under him, I found myself suspended, blinking at the camera before I fell. I enlisted in the Army and drove tanks around for a couple years. After I served my time, while I was packing away my uniforms in my parents attic, I came across my old saxophone. I remembered the man down the street who played with Benny Goodman and I soon found myself at his doorstep. Joe Kent. He was old, frail, yet the Jazz flowed through him. An energy source that he had tapped, deep in the hearts of everyone who listened. I became his waiter, his lackey, his driver, and his student. He taught me how to listen. How to listen to a record and hear the notes float over the changes. How to listen to the bass, to ride it through the song. How to listen to the sound the horn made. How to listen to the beating of your own heart in ¾ time.

I watched a cargo ship get loaded with large, metal crates and then depart. Hunger and music pulled me back to the club. I was still depressed, but I could tolerate it.

A couple days later, as I walked in the door of Orpheus, the manager told me that Rachael’s office had called asking if I had seen her; she had not come in for the past few days.

There was no answer at the door, so I picked the lock. Going through her apartment, I came across and address book. A page had been torn out. Using a trick I had learned on Saturday morning cartoons, I rubbed over the page behind with charcoal, leaving behind the message that had been impressed. It was not too far from her campus. I walked over there and rang the bell. An elderly lady answered the door.

“Yes, may I help you?”

“Ma’am, I would like to ask you about Rachael Cullins, if that is all right with you?”

“I trust your intentions are honorable?”

“Oh, yes Ma’’am. They are. I’m just a friend. She has disappeared and no one really knows for sure where she is.”

“Oh, my. Please come in.”

I noticed that she was a very proper lady. The house was small and immaculate. “Please have a seat. Would you like care for a some hot chocolate?”

“Yes, please. Ma’am, how did you know Rachael?”

“Miss Cullins was a boarder. I have a small apartment upstairs that I let out. She left about four months ago.”

“Do you know why she left.”

She frowned at and looked over her spectacles at me. “She had a boyfriend. Oh, he was something. To look at him, he was something out of those posers you see down town. Big Smile, Blond hair.”

“So what was the problem?”

“He was a brute. Sometimes I would see her wearing dark glasses. And occasionally I would see her with a black eye or a bruise that she couldn’t cover up. Once I saw her limping. One day she just ran out. She came back later for her belongings.”

“Did he live here with her?”

“Practically. He was here almost every night, always very polite to me. But I could see her eyes when he came that she dreaded meeting him.”

“DO you know his name?””

“I never found out. He liked to be called Aussie, but I think that was because he surfed.”

“Did Rachael have any friends around here that you know of? Did anyone come to see her?”

“She studied with a few different girls. I remember one. Kim, I believe her name was. Italian. Kim Napoli, I believe.”

“Ma’am, thank you for your time. You can’t imagine how much this means to me.”

“You must let me know when you find her. You will won’t you?”

“Of Course.”

I called the student directory on a pay phone and found Kim Napoli’s phone number. She wasn’t in, but I left a message on the tape player, and then went off to the club.

As I walked in, I saw a ghost. Desiré walked up to me and kissed me on the cheek. “Hey soldier. Long time no see.”

My look must have been ice. All the emotions just solidified and I froze. I couldn’t move. Fear, anger, hurt, confusion, worry rage. I could feel myself glowing read. She took a step back and turned away. She turned back to look at me, and then walked past me out the door.

<figure class="wp-block-image size-large">"Man," He Said to me in my Memory...</figure>

“Hey, Adam. What the hell? Snap out of it.” It was Bill, the Bartender. “Here, have a drink. He handed me something but I shook my head. I went up on stage and played. The crowd, who normally came to hear my extremely mellow sound must have been shocked. Because I played a sixty-five minute set, all above two forty on the metronome, all one straight jam. I took about four different solos. After that set, I fell down to me knees and started to cry. Bill closed up early and drove me home. At the door he said, “I don’t know what came over you tonight. You were incredible. I know that’s not what any one expected to hear, but…” He was speechless. I let myself in and collapsed on the bed. The digital clock said 1:00.

The phone ringing woke me up bolt upright. I was wired, the adrenaline pumping. The clock said 3:30. I picked up the receiver. “Hello?”

“Adam, help me.” It was Rachael.

“Rachael, where are you?” I shouted into the phone but there was no answer. “Rachael!” but the line was dead.

I can’t describe the emotion. I felt elated that she hadn’t just run out on me, guilty for feeling happy, and scared for her.

I went to my bureau. In the top drawer I had a 357 Magnum. I had bought it off a guy in my platoon who needed the money. He got transferred before he could buy it back. I had six rounds left from the one time I took it to the range. I stuck it in my belt and pulled my jacket over it. Down in the street, I managed to find a cab to take me to the college. Kim Napoli lived in one of the dorms. An undergrad coming out left the door open for me. I ran up the three flights of stairs to her room. Stepping over some junk in the hall. I noticed my watch said 4:05.

I banged on the door several time. She came to door asleep, a nightgown pulled tight around her. “Kim, listen. I know you don’t know me. Your friend Rachael is in trouble and I have to find her. Do you have any idea where she could be?”

“What,” she mumbled slowly coming awake. “Rachael who?”

“Rachael Cullens. You studied with her from time to time.”

“Oh, yeah. No, I haven’t seen her in months. We don’t have any of the same classes anymore.”

“Who is this guy, her boyfriend, Aussie?”

“Yeah that’s him.”

“What’s his real name? Where does he live?”

“Why?”

“She’s missing. He…may know where she is.”

“His name is Jason Peters. He lives in the Omega house.”
“Where is that?”

“Across the square. Go out the front door and take a left. It has the letters across the top. Omega looks like…”

I didn’t hear the rest of her sentence. I ran across the square. The Omega house had obviously just suffered an end of semester fiesta. There were numerous beer cans, cups, papers, napkins, and other assorted debris scattered across the front lawn. I banged on the front door. 4:28.

“What do you want?”

“Where is Jason Peters?”

“Who wants to know?”

“Listen, buddy, there is a girl in trouble somewhere, and I have got to find him.”

“Well, we brothers aren’t supposed to…”

I pulled out the pistol and held it between his eyes. “Listen, man, I don’t have time for this. Where the fuck is he?” I was raging. He almost passed out. I grabbed him by the shirt and shook him.
“he, he, he, he has a place up north, where he takes off to for the vacations. For all I know that’s where he is.”

“Where?” He told me the town the the road. I guess they had partied up there once so he had a pretty good idea where it was.

At the nearest main street I waved down a cab. 4:49. When I told the driver the location, he demanded the money up front. Since I was practically broke, except for a visa card, he refused to take me. The next cabby pulled over, saw the magnum in my belt and took off. 5:14. Giving up on the cabs I ran to the train station. 5:35. I bought a ticket. The next train didn’t depart until 9:05. I had time to try and think of a plan, but my mind could only think of her. Her sad eyes. Her dark voice on the phone. People were giving me uneasy looks. As I paced back and forth. A guy offered me a cigarette. Finally, as I was about to explode, the train came and I got on. During the ride I paced the length of the train and beat my hands against the windows.

I walked down the path to the house. It was a vacation house on the side of a lake. Aussie must have a tidy sum of money, because he had a sizable chunk of real estate. The house was two-storied. From what the brother at the door had told me, Aussies room faced the lake upstairs. There was only one car in the driveway—a black pickup truck with ornate chrome and a car-phone antenna. The front door was locked. I went around back. That, too was locked. There was an oak tree that had a limb that reached out onto the roof. I climbed down enough so that I could lower myself to the window. I slowly worked it open, my hands almost numb in the January air. A few flakes spin past me as I snaked my way into the house.

The room I entered must have been the parents room. I walked around the double bed and opened the door to the hall. I heard voices through the door across from me. Reaching for the pistol, I realized it must have fallen out of my belt as I climbed in. Cursing, I put my ear against the door.

“Come on, Rachael, you have to eat something. You haven’t eaten for days. Listen, if you are still mad about that first night, don’t be. You have to admit it has been a long time.”

All the world focused on that voice behind the door. I felt cold, like a machine. I crashed through the door and my fingers found his throat., just as the Drills had taught us to do in Basic. His hand caught my wrist, broke my watch band. Four second and he slumped unconscious. My fingers stayed locked. Kill. Death. Blood. Silence his life. Still.

Then I heard it. Like a bass, low, soothing. Pleading. I looked up. Rachael sat there, curled up like a fetus. Her blue eyes unfocused. Lost.

I remembered Joe.

“Man,” he said to me in my memory. ‘The Jazz is everywhere. It ain’t just music. It ain’t just blues. It’s the felling you get when you’re with a lady. It’s seeing home again after a year on the road. It’s the feeling when the drummer misses a beat and when you wake up with a hangover. If you let it, it can ruin you. Look at Bird. But if you know how to listen, and ride it right, it can give you peace as you have never known before.” Just then, as I had never heard it before, I understood Jazz. I could see the notes fly by my eyes and in the air I breathe.

<figure class="wp-block-image size-large">Sax, sheet music, and Neon Bar Sign<figcaption class="wp-element-caption">Image at the end of the article. unattributed.</figcaption></figure>

My grip loosened. I saw the red impressions of my fingers on his neck. I stood up beside her and looked in those frozen eyes.

We took the train back to the city. I took her to her apartment, put her to bed, and slept on the couch. The next morning, I spent my last few dollars on groceries and made breakfast. She didn’t eat. That night I took her with me to the Orpheus. Bill said he would keep an eye on her for me as I set up backstage.

I opened my case and took out my horn. The cold metal warmed to my touch. The horn assembled itself under my fingers. The reed touched my lips, wetting itself, then fit to the mouthpiece, lining up tip to tip. The mouthpiece slid on the cork to the line worn by pressure. The strap lay around my neck. The hook secured the saxophone to my body. The horn rested on my thumbs. My fingers rested on the keys.

I walked out front and onto the stage. The rhythm section looked to me and I said, “Follow my lead.” The horn and I fused into one musician and Jazz flowed. Dark blue smoke filled the air. The music was like electricity. Instead of me playing the horn, the horn and I were both played by the music. When I looked up, the icy film over Rachael’s eyes had melted and rolled down her cheek.

A couple days later, I stopped by her apartment. I knocked on the door. She looked though the peephole and then unlatched the door. Most of her belongings were packed in boxes stacked in the living room. “How are you doing?” I asked.

“”Okay. I called the police and they arrested Au…” she shook her head. “I’m going home for a while.”

I helped her pack up the rest of her stuff. Her father came over a half hour later and we loaded up a U-Haul. Her father for in the car. She opened the front door., then looked at me nervously. “Will you testify? In court?”

“Of course.”

She sighed. She looked down at the street and then up at me. A half smile played across her face. She gave me a peck on the cheek and then got into the car. I stepped back as her father put the car into drive and pulled out into the street. I turned up my collar against the cold and walked to the subway.

Episode 395 – Uncertainty, trust, and security

Posted by Josh Bressers on October 02, 2023 12:00 AM

Josh and Kurt talk about uncertainty. There are a bunch of stories in the news lately that really just boil down to uncertainty. Uncertainty is incredibly dangerous for everyone. We are afraid of uncertainty, and often don’t really understand why it is. Trust is like a currency and uncertainty erodes trust faster than almost anything else.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3223-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_395_Uncertainty_trust_and_security.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_395_Uncertainty_trust_and_security.mp3</audio>

Show Notes

Error building Kernel ln: target ‘+/source’: No such file or directory

Posted by Adam Young on September 25, 2023 04:47 PM

I have battled this problem a couple times and so I am documenting the issue and solution here.
Here is the error message from make modules_install

ln: target '+/source': No such file or directory

The short solution is to watch out for stray whitespace in the Makefile

This happens when I attempt to modify the Makefile in order to revision control the Kernel. I I suspect that a build I am about to make will prevent the machine I am working on from booting, I want to keep an older build functional in order to restore the machine.

Here is the diff for my Makefile:

diff --git a/Makefile b/Makefile
index 2fdd8b40b7e0..cb747c16e33c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 6
 PATCHLEVEL = 5
-SUBLEVEL = 0
+SUBLEVEL = 5
 EXTRAVERSION =
 NAME = Hurr durr I'ma ninja sloth

When the run fails, the diff will show a stray whitespace character around the SUBLEVEL value. This value is used to generate the string the becomes part of the path where the install happens. At the top level, Kernels get installed into here:

# ls -la /usr/lib/modules/
total 20
drwxr-xr-x.  8 root root  122 Sep 25 08:15 .
dr-xr-xr-x. 34 root root 4096 Sep 18 09:51 ..
drwxr-xr-x.  8 root root 4096 May 15 19:06 5.17.5-300.fc36.aarch64
drwxr-xr-x.  8 root root 4096 Sep 18 09:53 6.2.15-100.fc36.aarch64
drwxr-xr-x.  3 root root 4096 Sep 22 10:26 6.5.0+
drwxr-xr-x.  2 root root    6 Sep 23 07:42 6.5.1
drwxr-xr-x.  2 root root    6 Sep 23 07:57 6.5.5
drwxr-xr-x.  3 root root 4096 Sep 25 08:18 6.5.5+

The source directory is a symlink underneath it:

# ls -la /usr/lib/modules/6.5.5+/source
lrwxrwxrwx. 1 root root 11 Sep 25 08:15 /usr/lib/modules/6.5.5+/source -> /root/linux

Thus by having an extra space anywhere in there, the path generation gets messed up.

Episode 394 – The lie anyone can contribute to open source

Posted by Josh Bressers on September 25, 2023 12:00 AM

Josh and Kurt talk about filing bugs for software. There’s the old saying that anyone can file bugs and submit patches for open source, but the reality is most people can’t. Filing bugs for both closed and open source is nearly impossible in many instances. Even if you want to file a bug for an open source project, there are a lot of hoops before it’s something that can be actionable.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3216-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_394_The_lie_anyone_can_contribute_to_open_source.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_394_The_lie_anyone_can_contribute_to_open_source.mp3</audio>

Show Notes

Make Haste Slowly

Posted by Adam Young on September 20, 2023 08:18 PM

In the software development world, we call it technical debt.


In the Army it was “Half-assed, full-blast. Don’t know where we are going but we should have been there yesterday.”

And the solution was told to be by a guy going through officer basic with me…after a long career as an NCO in Army Special Forces.


“Make Haste Slowly.”


It is ok to “just make it work.” But have a strict enough code review process that is happy to kick back semi-functional code to get it production quality.

Think of it like an English Essay: it is ok to show your teacher a rough draft, but expect lots of Red Ink and rewriting on it.


Unit Test Everything. Automated testing will catch when your change code that breaks other code. Visual and manual testing does not count. It has to be automated or it is not sufficient. Not writing unit tests is heavy tech debt.

Finding a line of code in the Kernel from a stack trace

Posted by Adam Young on September 20, 2023 08:14 PM

To find out what line a particular stack trace entry points to, use the script ./scripts/faddr2line for example If I have the line __get_vm_area_node+0x17c/0x1a8 I can run

./scripts/faddr2line vmlinux.o __get_vm_area_node+0x17c/0x1a8
__get_vm_area_node+0x17c/0x1a8:
__get_vm_area_node at /root/linux/mm/vmalloc.c:2579 (discriminator 1)

Episode 393 – Can you secure something you don’t own?

Posted by Josh Bressers on September 18, 2023 12:00 AM

Josh and Kurt talk about the weird world we live in how where we can’t control a lot of our hardware. We don’t really have control over most devices we interact with on a daily basis. The conversation shifts into a question of how can we decide what to trust and where. It’s a very strange problem we experience now.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3212-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_393_Can_you_secure_something_you_dont_own.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_393_Can_you_secure_something_you_dont_own.mp3</audio>

Show Notes

Episode 392 – Curl and the calamity of CVE

Posted by Josh Bressers on September 11, 2023 12:00 AM

Josh and Kurt talk about why CVE is making the news lately. Things are not well in the CVE program, and it’s not looking like anything will get fixed anytime soon. Josh and Kurt have a unique set of knowledge around CVE. There’s a lot of confusion and difficulty in understanding how CVE works.

<audio class="wp-audio-shortcode" controls="controls" id="audio-3208-10" preload="none" style="width: 100%;"><source src="https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_392_Curl_and_the_calamity_of_CVE.mp3?_=10" type="audio/mpeg">https://traffic.libsyn.com/opensourcesecuritypodcast/Episode_392_Curl_and_the_calamity_of_CVE.mp3</audio>

Show Notes