<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl" media="all"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Roastidio.us Tagged with linux</title>
<link>https://roastidio.us/tag/2428</link>
<atom:link href="https://roastidio.us/tagged_with/linux" rel="self" type="application/rss+xml"></atom:link>
<description>Roastidio.us Tagged with linux</description>
<item>
<title>Weird Things Are Afoot In The Honeypot</title>
<link>https://carteryagemann.com/android-ssh.html</link>
<guid isPermaLink="false">itk5vGDF-TbE_HaARsO7nZ6cpWj9JIMg8SJAXw==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>Here&#39;s something you don&#39;t see every day. The logs from my SSH honeypot show someone brute-forcing the password for root and then executing: ls /data/data/com.android.providers.telephony/databases This is a strange directory to look for because it&#39;s where Android devices store the SQLite databases for SMS …</description>
<content:encoded>&lt;p&gt;Here&amp;#39;s something you don&amp;#39;t see every day. The logs from my SSH honeypot show
someone brute-forcing the password for root and then executing:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;ls /data/data/com.android.providers.telephony/databases&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a strange directory to look for because it&amp;#39;s where Android devices
store the SQLite databases for SMS messages and contacts. Why would an attacker
except an SSH server on the internet to be an Android device? Are there IoT
devices based on Android that run SSH servers and also store contacts? If
someone knows, please tell me!&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Debian Apt Repo for libipt</title>
<link>https://carteryagemann.com/libipt-repo.html</link>
<guid isPermaLink="false">mUpmApqZvf0rTLwP_j4MVLBcBCChWv-38cch9g==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>As part of my Ph.D. research, I play around with Intel Processor Trace a lot. As a result, I frequently use libipt; both as a library for my own software and for the reference programs it includes. ptdump and ptxed are my goto utilities for quickly checking and manipulating …</description>
<content:encoded>&lt;p&gt;As part of my Ph.D. research, I play around with Intel Processor Trace a lot.
As a result, I frequently use &lt;a href=&quot;https://github.com/01org/processor-trace&quot;&gt;libipt&lt;/a&gt;;
both as a library for my own software and for the reference programs it includes.
&lt;code&gt;ptdump&lt;/code&gt; and &lt;code&gt;ptxed&lt;/code&gt; are my goto utilities for quickly checking and
manipulating traces. They&amp;#39;re super useful!&lt;/p&gt;&lt;p&gt;Sadly on Debian and Ubuntu, the default package repositories only have a package
for the main library (no pre-compiled program binaries) that is woefully out
of date (last update was in 2016). Having to repeatably compile
&lt;a href=&quot;https://github.com/intelxed/xed&quot;&gt;xed&lt;/a&gt; and
&lt;a href=&quot;https://github.com/01org/processor-trace&quot;&gt;libipt&lt;/a&gt;
from source quickly got annoying, so I&amp;#39;ve decided to publish my own repository. I&amp;#39;ve
also made it public in hopes that others will find it useful.&lt;/p&gt;&lt;p&gt;The repository tracks the master branch on &lt;a href=&quot;https://github.com/01org/processor-trace&quot;&gt;libipt&lt;/a&gt;
and &lt;a href=&quot;https://github.com/intelxed/xed&quot;&gt;xed&lt;/a&gt;, so its packages should always contain
the latest code. I&amp;#39;ve made adding it to apt super easy:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;sh-c&amp;quot;$(wget-qO-https://super.gtisc.gatech.edu/libipt.sh)&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It currently has the following libraries:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;libxed&lt;/li&gt;&lt;li&gt;libxed-dev&lt;/li&gt;&lt;li&gt;libipt (includes the sideband library)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And the following pre-compiled programs:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;ptdump&lt;/li&gt;&lt;li&gt;pttc&lt;/li&gt;&lt;li&gt;ptxed&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;More information about these libraries and programs is available in their respective
documentation. I hope to add more packages in the coming days.&lt;/p&gt;&lt;p&gt;For people interested in learning how to host their own repositories, I built this
server using &lt;a href=&quot;https://www.gocd.org/&quot;&gt;gocd&lt;/a&gt;, &lt;a href=&quot;https://www.aptly.info/&quot;&gt;aptly&lt;/a&gt;, and
&lt;a href=&quot;https://httpd.apache.org/&quot;&gt;apache&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>How ASLR Helps Enable Exploits (CVE-2013-2028)</title>
<link>https://carteryagemann.com/aslr-enables-exploit.html</link>
<guid isPermaLink="false">7T0PRYV9IcrFjVh7OcFfExa6ayrh2dKSF42J2w==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>The other day I was playing around with CVE-2013-2028 along with my peer Hong Hu when we came across something odd: CVE-2013-2028 is only exploitable on 64-bit GNU/Linux when ASLR is enabled. After confirming this observation multiple times, we were left very surprised. How could ASLR possibly worsen the …</description>
<content:encoded>&lt;p&gt;The other day I was playing around with &lt;a href=&quot;https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-2028&quot;&gt;CVE-2013-2028&lt;/a&gt;
along with my peer &lt;a href=&quot;https://www.cc.gatech.edu/~hhu86/&quot;&gt;Hong Hu&lt;/a&gt; when we came across
something odd: &lt;em&gt;CVE-2013-2028 is only exploitable on 64-bit GNU/Linux when ASLR is &lt;/em&gt;&lt;em&gt;enabled&lt;/em&gt;&lt;em&gt;&lt;em&gt;.
After confirming this observation multiple times, we were left very surprised.
How could ASLR possibly &lt;/em&gt;worsen&lt;/em&gt; the security of an application? Driven by
curiosity, we decided to find the root cause of this result. Ultimately, we
had to go all the way to the Linux kernel code to find our answer. What we
found was a kernel quirk that can&amp;#39;t really be called a bug from the kernel&amp;#39;s
perspective, but does go against the expectations of the user.
So without further ado, allow
me to share how ASLR can enable the exploitation of applications.&lt;/p&gt;&lt;p&gt;For those unfamiliar with CVE-2013-2028, all that needs to be known is it&amp;#39;s an
exploitable vulnerability in older versions of nginx stemming from a stack
buffer overflow that can be triggered by specially crafted HTTP requests.
The bug occurs because an integer provided to nginx by the user that is intended
to be an unsigned value is accidentally casted temporarily into a signed value.
If an attacker passes a sufficiently large value, the worker thread handling the
request will copy too much data from its network socket into a fixed sized buffer
causing the stack to get smashed.
For the curious reader, a more in-depth analysis is available
&lt;a href=&quot;https://www.vnsecurity.net/research/2013/05/21/analysis-of-nginx-cve-2013-2028.html&quot;&gt;here&lt;/a&gt;
and a repository for reproducing it is available
&lt;a href=&quot;https://github.com/kitctf/nginxpwn&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;So why is this bug only exploitable when ASLR is turned on? We can find the
user space answer with a simple &lt;code&gt;strace&lt;/code&gt;. If we make a chunked HTTP request and
claim the total size is going to be &lt;code&gt;0xaaaaaaaaaaaaaaaa&lt;/code&gt;, nginx&amp;#39;s worker will
make a &lt;code&gt;recvfrom()&lt;/code&gt; system call for &lt;code&gt;0xaaaaaaaaaaaaaab0&lt;/code&gt; bytes from the network
socket. When ASLR is turned on, the Linux kernel will copy our request (which is
not actually &lt;code&gt;0xaaaaaaaaaaaaaaaa&lt;/code&gt; bytes long) into the worker&amp;#39;s buffer, smashing
the stack. However, when ASLR is turned off, the kernel will return &lt;code&gt;-EFAULT&lt;/code&gt; and
the worker will safely report the error and close the session.&lt;/p&gt;&lt;p&gt;We could stop here, but Hong and I were not satisfied. Why is the kernel returning
&lt;code&gt;-EFAULT&lt;/code&gt; when ASLR is disabled but not when it is enabled? The space allocated for
the stack is the same in both cases, so that can&amp;#39;t be the problem. The only obvious
difference is ASLR moves the stack&amp;#39;s address range to randomize it. When ASLR
is disabled, the stack&amp;#39;s highest address is placed at the boundary between user and
kernel space, which is &lt;code&gt;0x7fffffffffff&lt;/code&gt; in Linux kernels compiled for &lt;code&gt;x86_64&lt;/code&gt;. However,
&lt;code&gt;0xaaaaaaaaaaaaaab0&lt;/code&gt; is such a large number it shouldn&amp;#39;t matter where the stack is
placed. It&amp;#39;s not going to fit into the memory segment and it&amp;#39;s going to cross the
boundary. So what&amp;#39;s really happening in the kernel when it handles a &lt;code&gt;recvfrom()&lt;/code&gt;
system call?&lt;/p&gt;&lt;p&gt;Taking a look at Linux&amp;#39;s
&lt;a href=&quot;http://elixir.free-electrons.com/linux/v4.9-rc4/source/net/socket.c#L1665&quot;&gt;implementation&lt;/a&gt;
of &lt;code&gt;recvfrom()&lt;/code&gt;, we see the following code:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;SYSCALL_DEFINE6(recvfrom,int,fd,void__user*,ubuf,size_t,size,unsignedint,flags,structsockaddr__user*,addr,int__user*,addr_len){structsocket*sock;structioveciov;structmsghdrmsg;structsockaddr_storageaddress;interr,err2;intfput_needed;err=import_single_range(READ,ubuf,size,&amp;amp;iov,&amp;amp;msg.msg_iter);if(unlikely(err))returnerr;sock=sockfd_lookup_light(fd,&amp;amp;err,&amp;amp;fput_needed);if(!sock)gotoout;msg.msg_control=NULL;msg.msg_controllen=0;/* Save some cycles and don&amp;#39;t copy the address if not needed */msg.msg_name=addr?(structsockaddr*)&amp;amp;address:NULL;/* We assume all kernel code knows the size of sockaddr_storage */msg.msg_namelen=0;msg.msg_iocb=NULL;if(sock-&amp;gt;file-&amp;gt;f_flags&amp;amp;O_NONBLOCK)flags|=MSG_DONTWAIT;err=sock_recvmsg(sock,&amp;amp;msg,flags);if(err&amp;gt;=0&amp;amp;&amp;amp;addr!=NULL){err2=move_addr_to_user(&amp;amp;address,msg.msg_namelen,addr,addr_len);if(err2&amp;lt;0)err=err2;}fput_light(sock-&amp;gt;file,fput_needed);out:returnerr;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This code performs two relevant checks. The first occurs in:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;err=import_single_range(READ,ubuf,size,&amp;amp;iov,&amp;amp;msg.msg_iter);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the second occurs in:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;err2=move_addr_to_user(&amp;amp;address,msg.msg_namelen,addr,addr_len);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, we can rule out &lt;code&gt;move_addr_to_user()&lt;/code&gt; because it&amp;#39;s passed
the number of bytes &lt;em&gt;actually&lt;/em&gt; fetched from the socket, which is the same in
our attack regardless of ASLR. This leaves &lt;code&gt;import_single_range()&lt;/code&gt;, which is
&lt;a href=&quot;http://elixir.free-electrons.com/linux/v4.9-rc4/source/lib/iov_iter.c#L1207&quot;&gt;implemented&lt;/a&gt;
as follows:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;intimport_single_range(intrw,void__user*buf,size_tlen,structiovec*iov,structiov_iter*i){if(len&amp;gt;MAX_RW_COUNT)len=MAX_RW_COUNT;if(unlikely(!access_ok(!rw,buf,len)))return-EFAULT;iov-&amp;gt;iov_base=buf;iov-&amp;gt;iov_len=len;iov_iter_init(i,rw,iov,1,len);return0;}EXPORT_SYMBOL(import_single_range);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this function, a sanity check is performed via &lt;code&gt;access_ok()&lt;/code&gt; to make sure
the number of bytes requested by the caller cannot cause a write that would
cross into kernel space. But as we pointed out before, the value nginx&amp;#39;s worker
is passing here is &lt;code&gt;0xaaaaaaaaaaaaaab0&lt;/code&gt;, which should easily cross the boundary
regardless of ASLR. The type &lt;code&gt;size_t&lt;/code&gt; is defined as an unsigned 64-bit integer
in our case, so &lt;code&gt;access_ok()&lt;/code&gt; should be passed &lt;code&gt;0xaaaaaaaaaaaaaab0&lt;/code&gt;, right?
Actually, if we look more closely, we can see the following lines enforce a
limit on &lt;code&gt;len&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;if(len&amp;gt;MAX_RW_COUNT)len=MAX_RW_COUNT;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we lookup &lt;code&gt;MAX_RW_COUNT&lt;/code&gt;, we can see it equals &lt;code&gt;(INT_MAX &amp;amp; PAGE_MASK)&lt;/code&gt;,
which turns out to be a 32-bit value. So in other words, even though &lt;code&gt;recvfrom()&lt;/code&gt;
allows 64-bit unsigned integer lengths on &lt;code&gt;x86_64&lt;/code&gt;, &lt;code&gt;import_single_range()&lt;/code&gt; truncates
them into 32-bit unsigned integers! On a 64-bit processor, this truncation
combined with ASLR&amp;#39;s relocation of the stack allows our attack to pass the
&lt;code&gt;access_ok()&lt;/code&gt; check and smash nginx&amp;#39;s stack.&lt;/p&gt;&lt;p&gt;Technically, this isn&amp;#39;t a bug from the
kernel&amp;#39;s perspective because &lt;code&gt;import_single_range()&lt;/code&gt; also calls &lt;code&gt;iov_iter_init()&lt;/code&gt;
with the truncated length. This means &lt;code&gt;recvfrom()&lt;/code&gt; can only receive up to the truncated
length worth of bytes from the socket and therefore passing the truncated value to
&lt;code&gt;access_ok()&lt;/code&gt; is safe.&lt;/p&gt;&lt;p&gt;That said, it&amp;#39;s a really odd way of implementing this system call. From the caller&amp;#39;s
perspective, it&amp;#39;s not made clear that even though it can pass a 64-bit length, only
the lower 32-bits will be considered. Also &lt;code&gt;recvfrom()&lt;/code&gt; treats the length as 64-bits
all the way through its logic, so it&amp;#39;s not immediately obvious that the length is
being truncated by &lt;code&gt;MAX_RW_COUNT&lt;/code&gt;. Additionally, as Hong and I discovered, there
is a security consequence to this choice. Performing the &lt;code&gt;access_ok()&lt;/code&gt; check on
the truncated length allows network attacks that rely on integer overflow and
underflow to succeed where they would otherwise more likely be blocked by the kernel
due to a failed system call. We find this to be an interesting consequence since
it results from seemingly unrelated design decisions. It is hard to recommend that
the Linux kernel developers revise &lt;code&gt;import_single_range()&lt;/code&gt; given that the real
problem is a bug in nginx and not the Linux kernel itself, but we find this
discovery fascinating regardless.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Intel PT Data at Rest: A Compression Experiment</title>
<link>https://carteryagemann.com/pt-data-at-rest.html</link>
<guid isPermaLink="false">tcRZg-TjQRWuoE_fjKkOcAEKBJ5R7i59uCi-_g==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>Full Disclosure: I am a researcher in Georgia Tech&#39;s ISTC-ARSA, which is funded by Intel. Although I reference two publications that share Xinyang Ge and Weidong Cui as authors, I am neither associated with them nor Microsoft Research at the time of writing. Intel Processor Trace (PT) is a powerful …</description>
<content:encoded>&lt;p&gt;&lt;em&gt;Full Disclosure: I am a researcher in Georgia Tech&amp;#39;s
&lt;a href=&quot;http://istc-arsa.iisp.gatech.edu&quot;&gt;ISTC-ARSA&lt;/a&gt;, which is funded by
Intel. Although I reference two publications that share Xinyang Ge and Weidong Cui as
authors, I am neither associated with them nor Microsoft Research at the time
of writing.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Intel Processor Trace (PT) is a powerful hardware feature for recording the
behavior of CPUs. With it, developers and researchers can monitor the
control-flow path taken by threads, hardware interrupts, and more, all with
cycle-accurate timing. However, this rich stream of data comes at the cost of
size. Depending on what PT is configured to trace, it can output &lt;em&gt;hundreds of
megabytes&lt;/em&gt; of data &lt;em&gt;per second per core&lt;/em&gt;. PT does take steps to save bandwidth by
only recording changes in control-flow, excluding redundant high-order bits
in target addresses, and compressing returns leading to predictable locations. However,
despite this compression, the volume of data is still massive.&lt;/p&gt;&lt;p&gt;As a consequence, much of the work
published so far handles tracing in one of two ways. One option is to consume the
trace as it is generated. This works as long as the consumer can keep up with the
producer, which is the case in the control-flow integrity (CFI) system
&lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2017/01/griffin-asplos17.pdf&quot;&gt;Griffin&lt;/a&gt;.
The other common approach is to configure PT to write in a circular
buffer. This option is suitable for crash dump analysis systems like
&lt;a href=&quot;https://dl.acm.org/authorize?N47279&quot;&gt;Snorlax&lt;/a&gt;, which only need a fixed size
window into a thread&amp;#39;s past.&lt;/p&gt;&lt;p&gt;However, while some applications are feasible using the two previous methods,
there are still situations were it is desirable to store the entire trace for
postmortem analysis. If nothing else, it is useful for repeatable experiments.
With this in mind, I performed a naive experiment last night to explore if
more can be done to compress PT traces when &lt;em&gt;the data is at rest&lt;/em&gt;. Based on the
observations that the compression PT applies is highly localized (i.e. a target
address verses the previously recorded target address and a return verses the
previously recorded call) and that programs often execute repetitive loops,
I hypothesized that even a general purpose compression algorithm should
be able to compress traces with a good ratio.&lt;/p&gt;&lt;h2&gt;Procedure&lt;/h2&gt;&lt;p&gt;The overall idea for the experiment is very simple: gather some PT traces,
compress them with a commonly used algorithm, and compare the sizes.
For a subject I used the simple HTTP server that comes with Python 2.7 to host
a copy of this blog. For each trial I had a crawler request pages from the
server for a set duration. Once the time expired, I terminated the server and
crawler and stopped the tracing. I then compressed the trace using the GNU/Linux
utility &lt;code&gt;gzip&lt;/code&gt;, which uses Lempel-Ziv coding. I also fed it through a
disassembler that matches the PT packets to the binary&amp;#39;s static code to
produce a linear sequence of instructions. From this I counted the number of
unique basic blocks executed during the trace to serve as a rough proxy for code
coverage. To summarize the procedure:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Configure and enable PT tracing.&lt;/li&gt;&lt;li&gt;Start the Python HTTP server.&lt;/li&gt;&lt;li&gt;Start the crawler.&lt;/li&gt;&lt;li&gt;Wait for a specified duration.&lt;/li&gt;&lt;li&gt;Terminate the crawler and server.&lt;/li&gt;&lt;li&gt;Stop PT tracing.&lt;/li&gt;&lt;li&gt;Compress the resulting trace and count the number of unique basic blocks executed.&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;Results&lt;/h2&gt;&lt;p&gt;&lt;img src=&quot;https://carteryagemann.com/images/pt-at-rest-fig1.png&quot; alt=&quot;Figure 1&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Comparing the original size of the PT trace to the size after compression
produces the above graph. Both plots best match linear regressions and are
increasing over time. However, the size of the compressed traces increases
at a slower rate than the uncompressed traces, meaning these two plots are
diverging as time increases.&lt;/p&gt;&lt;p&gt;Another observation to note is the large volume of
trace data produced during the server&amp;#39;s startup.
This explains why even the shortest trial produced a 1GB trace.
For the same reason, counting the number
of unique basic blocks turned out to not be useful. The number of new basic
blocks executed while serving requests was small.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://carteryagemann.com/images/pt-at-rest-fig2.png&quot; alt=&quot;Figure 2&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;The next graph shows the relationship between the compressed and uncompressed
sizes as a &lt;a href=&quot;https://en.wikipedia.org/wiki/Data_compression_ratio#Definitions&quot;&gt;space savings&lt;/a&gt;
percentage. The plot best fits a linear regression and shows the savings
decreasing over time. This is likely due to the design of the underlying
compression algorithm, which is intended for general use and does not take into
consideration the unique characteristics of PT traces.&lt;/p&gt;&lt;p&gt;To summarize, this experiment shows that more can be done to compress PT traces
for storage at rest.&lt;/p&gt;&lt;h2&gt;Discussion&lt;/h2&gt;&lt;p&gt;It is understandable that the compression used by PT would produce small space
savings compared to general compression algorithms given the limitations of
hardware memory and Intel&amp;#39;s very strict performance overhead requirements. In practice,
PT produces an overhead of less than 4% in the worst case, and less
than 2% on average. These numbers are based on my own observations and the results
published by other researchers. In short, PT has very few clock cycles and very
little space available for performing compression.&lt;/p&gt;&lt;p&gt;Another factor that deserves consideration is compression&amp;#39;s impact on processing
time. For systems that consume PT traces on the fly, the largest source of
performance overhead is not PT tracing itself but rather the time spent
buffering and consuming it. In CFI, for example, the PT trace has to be
matched with the executed code in order to reconstruct control-flow. This is why
the authors of
&lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2017/01/griffin-asplos17.pdf&quot;&gt;Griffin&lt;/a&gt;
report a 11.9% overhead on the SPECint benchmark despite the 4% overhead of PT itself.
Adding better space saving compression could increase this overhead further.&lt;/p&gt;&lt;p&gt;That said, for storing PT traces at rest, more can be done to better conserve space.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Intel Processor Trace, execvp, and ptrace</title>
<link>https://carteryagemann.com/pt-execvp-ptrace.html</link>
<guid isPermaLink="false">JumpYGChytY9H1qYf9d68h4j09yGIkh1--CRgQ==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>Lately, I&#39;ve been playing around with Intel Processor Trace (PT); a x86 hardware feature that allows for complete tracing of process control flows. As part of my research, I&#39;ve been developing my own Linux driver and user program to control PT. Tracing can be configured using a handful of model …</description>
<content:encoded>&lt;p&gt;Lately, I&amp;#39;ve been playing around with Intel Processor Trace (PT); a x86
hardware feature that allows for complete tracing of process control flows.
As part of my research, I&amp;#39;ve been developing my own Linux driver and user
program to control PT.&lt;/p&gt;&lt;p&gt;Tracing can be configured using a handful of model specific registers (MSRs)
in the Intel CPU. One useful configuration supported by PT is CR3 filtering.
For those readers less familiar with x86 architecture, when a user process is
executed, the CPU&amp;#39;s CR3 register holds the physical address of the process&amp;#39;s
page table. Since every process has its own page table, each process will also
have a CR3 value that is unique from every other currently scheduled process.
By configuring PT to use a CR3 filter, tracing can be limited to a single
process.&lt;/p&gt;&lt;p&gt;Early versions of my program could only trace already running processes. I would
use the GNU debugger to start the target process and trap its first instruction
and then I would manually feed its PID into my program as an argument. The Linux
driver would then convert the PID into a CR3 by traversing the process&amp;#39;s task
structure (&lt;code&gt;virt_to_phys(task_struct-&amp;gt;mm_struct-&amp;gt;pgd)&lt;/code&gt;) and use this address to
configure PT (&lt;code&gt;IA32_RTIT_CR3_MATCH&lt;/code&gt;). Needless to say, having to manually start
and trap the target process got very tiring after repeated tracing.&lt;/p&gt;&lt;p&gt;To simplify tracing a process, I wanted my program to take as parameters the
file path of an executable and its arguments and automatically start and trace
the process. My first attempt roughly followed this pseudo code:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;pid=fork();if(pid==0){// Child process// Wait for parent to signal that PT is readyexecvp(target_program,args);}else{// Parent processenable_cr3_filter(pid);enable_pt();// Signal child that PT is ready}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Easy enough, right? I compiled the program, ran my first trace and got...
nothing.&lt;/p&gt;&lt;h2&gt;execvp and CR3&lt;/h2&gt;&lt;p&gt;So what went wrong? It turns out we can demonstrate the problem with a simple
test. Consider this simple C program:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;// test_1.c#include&amp;lt;stdio.h&amp;gt;#include&amp;lt;unistd.h&amp;gt;voidpid_to_cr3(){intm_pid=getpid();charpid_str[20];snprintf(pid_str,20,&amp;quot;%d&amp;quot;,m_pid);FILE*chardev=fopen(&amp;quot;/dev/pid_to_cr3&amp;quot;,&amp;quot;w&amp;quot;);fputs(pid_str,chardev);fclose(chardev);}voidmain(){char*argv[]={&amp;quot;./test_2&amp;quot;,NULL};intpid=fork();if(pid==0){// Child processpid_to_cr3();// printed to dmesgexecvp(argv[0],argv);}}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this example, &lt;code&gt;/dev/pid_to_cr3&lt;/code&gt; is a simple Linux character device that
processes can write a PID into and it will print the corresponding CR3 value
into the kernel log:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;// pid_to_cr3.cstaticunsignedlongpid_to_cr3(intpid){structtask_struct*task;structmm_struct*mm;void*cr3_virt;task=pid_task(find_vpid(pid),PIDTYPE_PID);if((uintptr_t)task&amp;lt;1)return0;mm=task-&amp;gt;mm;// mm can be NULL in cases such as kthreads, in which case we want the active_mmif(mm==NULL)mm=task-&amp;gt;active_mm;if(mm==NULL)return0;cr3_virt=(void*)mm-&amp;gt;pgd;returnvirt_to_phys(cr3_virt);}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After &lt;code&gt;test_1.c&lt;/code&gt; passes its PID to &lt;code&gt;/dev/pid_to_cr3&lt;/code&gt;, it then uses &lt;code&gt;execvp&lt;/code&gt; to
overwrite its memory with a new program: &lt;code&gt;test_2.c&lt;/code&gt;. This program simply passes
its PID to &lt;code&gt;/dev/pid_to_cr3&lt;/code&gt; as well:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;#include&amp;lt;stdio.h&amp;gt;#include&amp;lt;unistd.h&amp;gt;voidpid_to_cr3(){intm_pid=getpid();charpid_str[20];snprintf(pid_str,20,&amp;quot;%d&amp;quot;,m_pid);FILE*chardev=fopen(&amp;quot;/dev/pid_to_cr3&amp;quot;,&amp;quot;w&amp;quot;);fputs(pid_str,chardev);fclose(chardev);}voidmain(){pid_to_cr3();// printed to dmesg}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we compile these source files and execute &lt;code&gt;test_1&lt;/code&gt;, we expect that the PID
before and after executing &lt;code&gt;execvp&lt;/code&gt; will be the same because &lt;code&gt;execvp&lt;/code&gt; causes the
kernel to overwrite the caller&amp;#39;s own memory. But what happens to the CR3 value?
As it turns out:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;[ 1757.437572] PID 17319 = CR3 18759503872
[ 1757.438414] PID 17319 = CR3 18826612736&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rather than rewriting the existing caller&amp;#39;s page table when &lt;code&gt;execvp&lt;/code&gt; is called,
the Linux kernel actually allocates and populates an entirely new page table!
Since our original PT program was getting the CR3 &lt;em&gt;before&lt;/em&gt; the &lt;code&gt;execvp&lt;/code&gt;, our
trace wasn&amp;#39;t including the target program&amp;#39;s execution.&lt;/p&gt;&lt;h2&gt;ptrace&lt;/h2&gt;&lt;p&gt;So how do we get the CR3 value &lt;em&gt;after&lt;/em&gt;&lt;code&gt;execvp&lt;/code&gt; is called by the child? We can&amp;#39;t
simply have the parent signal the child, like in the first attempt, because any
code we give to the child process will be overwritten when &lt;code&gt;execvp&lt;/code&gt; is called.
The solution instead lies in an OS feature known as &lt;code&gt;ptrace&lt;/code&gt;. Using &lt;code&gt;ptrace&lt;/code&gt;, we
can have the child process attach itself to the parent process for debugging.
When &lt;code&gt;execvp&lt;/code&gt; is completed, the OS will pause the child and signal the parent.
The parent can catch this signal using &lt;code&gt;waitpid()&lt;/code&gt;, do whatever it needs to do,
and then resume the child. The code looks something like this:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;pid=fork()if(pid==0){// Child processptrace(PTRACE_TRACEME,0,NULL,NULL);execvp(args[0],args);}else{// Parent processwaitpid(pid,NULL,0);// Wait for child to complete execvp()enable_cr3_filter(pid);enable_pt();ptrace(PTRACE_DETACH,pid,0,0);// Resume child}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note that this code detaches the parent from the child once the child has been
paused. This causes the child to resume normal execution. If we wanted to
continue monitoring the child (for example, to detect &lt;code&gt;fork()&lt;/code&gt; or &lt;code&gt;clone()&lt;/code&gt;), we
could do so.&lt;/p&gt;&lt;p&gt;Making the above modification allows the parent to capture the correct CR3 value
and get a complete PT trace.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Getting the CR3 value for a PID in Linux</title>
<link>https://carteryagemann.com/pid-to-cr3.html</link>
<guid isPermaLink="false">Wdsdw-JGqEsUdp3ez3sPDNexaPPoyFhaZOSmVA==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>Writing low level code can be difficult due to the lack of examples on the internet. The answer is generally sitting somewhere in a 3,000 page manual where only the most dedicated programmers will find it. Last week I had such an experience. Currently my research involves a lot …</description>
<content:encoded>&lt;p&gt;Writing low level code can be difficult due to the lack of examples on the internet.
The answer is generally sitting somewhere in a 3,000 page manual where only the most dedicated programmers will find it.&lt;/p&gt;&lt;p&gt;Last week I had such an experience. Currently my research involves a lot of x86 specific programming and virtual machine introspection (VMI).
To test one of the proof-of-concept hypervisors I&amp;#39;m working on, I needed a way to quickly convert Linux PID values into the corresponding
value that gets loaded into the CR3 register when that process is executing on the CPU. For those who are unfamiliar with the x86 CPU architecture,
I recommend reading &lt;a href=&quot;https://www.kernel.org/doc/gorman/html/understand/understand006.html&quot;&gt;this page&lt;/a&gt; on Linux x86 page table management.
The short story is when a process is executed on an x86 CPU, the CR3 register is loaded with the &lt;em&gt;physical&lt;/em&gt; address of that process&amp;#39;s
&lt;em&gt;page global directory&lt;/em&gt; (PGD).
This is necessary so the CPU can perform translations from virtual memory address to physical memory addresses.
Since every process needs its own PGD, the value in the CR3 register will be unique for each scheduled process in the system.
This is very convenient for VMI because it means we don&amp;#39;t need to constantly scan the guest kernel&amp;#39;s memory to keep track of which process is
being executed. Instead, we can just monitor writes to the CR3 register.&lt;/p&gt;&lt;p&gt;However, just tracking changes to the CR3 register doesn&amp;#39;t give us much insight into what the guest kernel is doing.
This is commonly referred to as the &lt;em&gt;semantic gap&lt;/em&gt; problem. In order to cross this gap, we need to map the PID values of the processes we&amp;#39;re interested
in to their corresponding CR3 values. The following Linux kernel module code snippet does just that:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;#include&amp;lt;linux/module.h&amp;gt;#include&amp;lt;linux/kernel.h&amp;gt;#include&amp;lt;linux/sched.h&amp;gt;#include&amp;lt;linux/pid.h&amp;gt;#include&amp;lt;asm/io.h&amp;gt;unsignedlongpid_to_cr3(intpid){structtask_struct*task;structmm_struct*mm;void*cr3_virt;unsignedlongcr3_phys;task=pid_task(find_vpid(pid),PIDTYPE_PID);if(task==NULL)return0;// pid has no task_structmm=task-&amp;gt;mm;// mm can be NULL in some rare cases (e.g. kthreads)// when this happens, we should check active_mmif(mm==NULL){mm=task-&amp;gt;active_mm;}if(mm==NULL)return0;// this shouldn&amp;#39;t happen, but just in casecr3_virt=(void*)mm-&amp;gt;pgd;cr3_phys=virt_to_phys(cr3_virt);returncr3_phys;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should be noted that while the CR3 register is useful for tracking which &lt;em&gt;process&lt;/em&gt; is being executed, it cannot track which &lt;em&gt;thread&lt;/em&gt; is executing
because threads share memory and therefore will have the same PGD and CR3 value. Keeping track of the scheduling of threads via introspection is
a more complicated task and is a topic for another time.&lt;/p&gt;&lt;p&gt;For simplicity I implemented the conversion code as a Linux kernel module. If you&amp;#39;re interested in how to do this conversion using pure introspection
on an unmodified kernel, you should checkout &lt;a href=&quot;https://github.com/libvmi/libvmi/blob/master/libvmi/os/linux/memory.c#L145&quot;&gt;libVMI&amp;#39;s code&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>How Orange Helps You Sleep At Night</title>
<link>https://carteryagemann.com/how-orange-helps-you-sleep-at-night.html</link>
<guid isPermaLink="false">ZpjxxhtgmN68Nj533FH5W21cgCIqEtSgRxk8cA==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:24 +0000</pubDate>
<description>Originally written for the Syracuse University College of Engineering blog. Everyone at Syracuse University knows that orange is the very best college color, but who knew it could also help you sleep? Research conducted in recent years has shown that sleep problems are on the rise and one theory gaining …</description>
<content:encoded>&lt;p&gt;&lt;em&gt;Originally written for the Syracuse University College of Engineering blog.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Everyone at Syracuse University knows that orange is the very best college color, but who knew it could also help you sleep? &lt;a href=&quot;http://www.pnas.org/content/112/4/1232.full.pdf&quot;&gt;Research conducted in recent years&lt;/a&gt; has shown that sleep problems are on the rise and one theory gaining momentum points to our electronics as the cause. Studies find that the abundance of blue light produced by our smartphones, tablets, and computer screens has a tangible impact on the chemistry in our bodies that regulates when to wake up and when to go to sleep. This isn’t a problem during the day when the sun naturally produces its own blue light, but staring at our own personal mini sun before bed can make falling asleep much more difficult. So what can we do about it? We could restrict ourselves from staring at screens an hour before bedtime, but the world is a busy place and our nighttime reading isn&amp;#39;t always ink on paper. Instead, programmers are experimenting with software that reduces the level of blue light our screens produce after sunset. As the sun goes down, the screen shifts from a bluish glow to an orange tint and then back to blue with the following sunrise—promising a better night’s sleep for those of us that are unable (or unwilling) to give up our screens at night, This software is already publicly available for computers thanks to groups like &lt;a href=&quot;https://justgetflux.com/&quot;&gt;f.lux&lt;/a&gt;, but availability on mobile devices is limited. Luckily, the big companies have taken notice and are taking action. &lt;a href=&quot;http://www.apple.com/ios/preview/&quot;&gt;In an upcoming version of iOS for iPhones and iPads&lt;/a&gt;, Apple plans to introduce Night Shift. Flip it on and it&amp;#39;ll automatically determine when the sun sets and rises in your area and adjust the screen&amp;#39;s color accordingly. Just another reason to GO ORANGE.&lt;/p&gt;&lt;h3&gt;About The Author&lt;/h3&gt;&lt;p&gt;Carter Yagemann ’15 is a master’s student studying computer science in Syracuse University’s College of Engineering and Computer Science. A research assistant in Professor Kevin Du‘s Android security lab, his interests include mobile security and security education. He explores problems such as how to ensure security and privacy in Android inter-component communication. Yagemann is a student member of ACM and IEEE and competes in cybersecurity competitions with the Information Security Club in Syracuse University’s School of Information Studies (iSchool).&lt;/p&gt;</content:encoded>
</item>
<item>
<title>The importance of boot partitions in Linux systems.</title>
<link>https://carteryagemann.com/boot-partition.html</link>
<guid isPermaLink="false">vHBWee9yIgHXLpi2vJmBgJLhgh8fNGXhOywpBg==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:23 +0000</pubDate>
<description>Over the weekend, the lab I work in experienced a power outage. After power was restored, one of our servers failed to boot. It ultimately became my responsibility to figure out if the server could be repaired and failure wasn&#39;t an option because the server was configured (with no backups …</description>
<content:encoded>&lt;p&gt;Over the weekend, the lab I work in experienced a power outage. After power was restored, one of our servers failed to boot. It ultimately became my responsibility to figure out if the server could be repaired and failure wasn&amp;#39;t an option because the server was configured (with no backups) to run a bunch of services and hosted lots of data (with no backups) for many users. Typical sysop problem (lol), but our lab has no personnel for managing the systems; so there I was.&lt;/p&gt;&lt;p&gt;In the process of finding and fixing the issue, I learned a lot of specifics regarding how the Grub bootloader and Linux work during system boot, so I decided to document my experience for future reference by others. This documentation will be lengthy, so if you only care about avoiding this type of problem, skip ahead to the Remediation section.&lt;/p&gt;&lt;h2&gt;Finding the Problem&lt;/h2&gt;&lt;p&gt;The server in question was a Dell Poweredge T620 running Ubuntu. The server consisted of two Intel Xeon processors, about 128GB of RAM, and three 2TB hard drives connected to a RAID controller.&lt;/p&gt;&lt;p&gt;The problem occurred during system start-up. The BIOS would start Grub, and then Grub would produce the error &lt;code&gt;error: attempt to read or write outside of disk hd0&lt;/code&gt;. After that, the Linux kernel would start, but shortly after would spit out a stack trace and crash.&lt;/p&gt;&lt;p&gt;My first response was to run a disk check on the hard drives to make sure there weren&amp;#39;t any problems with their sectors, but this turned up nothing. The disks were operating normally. This meant that the problem was most likely related to Grub.&lt;/p&gt;&lt;h2&gt;Diagnosing the Problem&lt;/h2&gt;&lt;p&gt;Since the error message that was appearing was being generated by Grub, the next thing I did was try to manually start the Linux kernel. The easiest way to do this is to press &amp;#39;c&amp;#39; when the Grub menu appears. This will start a Grub command shell through which operating systems can be manually booted.&lt;/p&gt;&lt;h3&gt;Understanding Partitions&lt;/h3&gt;&lt;p&gt;Before explaining the commands I used while in the Grub command shell, I&amp;#39;ll summarize some basics regarding partitions here.&lt;/p&gt;&lt;p&gt;First, hard drives and their partitions can be accessed in Linux via the &amp;quot;/dev&amp;quot; directory. In most modern Linux systems, hard drives follow a naming convention which starts with &amp;quot;sd&amp;quot; followed by a letter designating the drive. &amp;quot;sda&amp;quot;, &amp;quot;sdb&amp;quot;, &amp;quot;sdc&amp;quot;, etc. Partition names are prefixed with a hard drive name followed by a digit designation. The hard drive &amp;quot;sda&amp;quot;, for example, might have the partitions &amp;quot;sda1&amp;quot;, &amp;quot;sda2&amp;quot;, and so forth in the &amp;quot;/dev&amp;quot; directory.&lt;/p&gt;&lt;p&gt;Grub also uses the notion of disks and partitions, but the naming syntax is a little different. The syntax takes the form of &amp;quot;hd#,#&amp;quot; where the first # represents the disk number and the second # represents the partition on that disk. So &amp;quot;hd0,1&amp;quot;, &amp;quot;hd0,2&amp;quot;, and so on.&lt;/p&gt;&lt;h3&gt;Boot Sequence&lt;/h3&gt;&lt;p&gt;While I&amp;#39;m covering general Linux background knowledge, I&amp;#39;ll also mention a portion of the boot sequence for Linux because this will also be important for understanding the Grub commands. In most Linux systems which boot using the BIOS (as opposed to newer EFI or UEFI booting) the critical pieces are: BIOS, Grub, initrd, and vmlinux.&lt;/p&gt;&lt;p&gt;BIOS stands for Basic Input Output System and is the first thing the system executes upon receiving power. Once the BIOS is started, it&amp;#39;ll perform some basic system checks and then load and execute the bootloader. There are many bootloaders out there, but Linux systems tend to use a particular one called Grub. Grub&amp;#39;s job is to load the pieces into memory that are necessary to start the operating system. In the case of Linux, the two important pieces which Grub needs to write into memory are initrd and vmlinux. I won&amp;#39;t discuss these files in great detail, but to explain them briefly, initrd is the initial RAM disk for the Linux operating system. What that means is that initrd contains a minimalistic copy of Linux comprising of only the kernel and essential programs. Grub will load it into memory and then execute it and it will start up the full Linux kernel contained in the vmlinux file. Once the full Linux kernel is booted, initrd will unload itself from memory.&lt;/p&gt;&lt;h3&gt;Diagnosing Grub&lt;/h3&gt;&lt;p&gt;Now that I&amp;#39;ve covered all the necessary background information, on to the Grub commands.&lt;/p&gt;&lt;p&gt;The first step is to find where the boot directory is on the system. First, list all the partitions on the system:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; ls&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will create a list of all the partitions on the system. The next step is to figure out which one contains Grub, initrd, and vmlinux (since we&amp;#39;re trying to boot a Linux operating system). This can also be done with the list command:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; ls (hd0,1)
grub&amp;gt; ls (hd0,1)/boot&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once we&amp;#39;ve found the location of the boot files, set that partition as Grub&amp;#39;s root directory:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; set root=(hd0,1)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I used &amp;quot;hd0,1&amp;quot; in the above commands, but you might find the boot files in a different partition. Either way, the boot files for a Linux system should always be either in the root directory of the partition (if that partition is a standalone boot partition) or in &amp;quot;/boot&amp;quot; (if that partition also holds other files).&lt;/p&gt;&lt;p&gt;After we&amp;#39;ve found the correct root partition, we next need to give Grub the names of the vmlinux and initrd files:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; /boot/vmlinux root=/dev/sda1
grub&amp;gt; initrd /boot/initrd&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note, the vmlinux command needs to be passed the parameter &amp;quot;root&amp;quot;. This parameter should be the partition which holds the Linux operating system. This may or may not be the same partition holding the boot files.&lt;/p&gt;&lt;p&gt;Once all the files have been specified, all that&amp;#39;s left is to boot the operating system:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;grub&amp;gt; boot&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this point, you&amp;#39;ll get a basic command shell for Linux. Of course, our lab&amp;#39;s server was failing to boot, so this didn&amp;#39;t happen. Instead, the error mentioned at the beginning appeared when I tried to execute the initrd command. Because of this, I now know that initrd is the problematic file. So how do we fix this?&lt;/p&gt;&lt;h2&gt;Remediation&lt;/h2&gt;&lt;p&gt;So what went wrong? Basically, the problem is with the partitions on the server&amp;#39;s hard drives. For some reason, when Grub tries to load the initrd file into memory, it reaches the end of what it can read from the hard drive before reaching the end of the file. In our case, the problem is that our RAID controller makes the hard drives appear as a single 4TB drive. This is quite large and the initrd file could reside anywhere in those 4TBs. As it turns out, Grub could not address the memory location of our initrd file and therefore couldn&amp;#39;t load it. So the power outage was not the direct cause of our problem. At some point, most likely during an Ubuntu update, the initrd file was modified and ended up in a location on the logical hard drive which Grub can&amp;#39;t reach.&lt;/p&gt;&lt;p&gt;The solution to this problem is to keep the boot files to a small partition which resides at the start of the hard drive. For those readers who skipped straight to this section, that&amp;#39;s all you need to know. When you install a Linux system, you really should make a dedicated 256MB partition for holding the boot files, despite the fact that most Linux installers do not require you to do this.&lt;/p&gt;&lt;p&gt;In my case, however, I couldn&amp;#39;t just reinstall the operating system, so in the following paragraphs I&amp;#39;ll describe how I migrated the boot files in my already existing Linux installation into a new dedicated boot partition.&lt;/p&gt;&lt;h2&gt;Creating a Boot Partition in an Existing Linux Installation&lt;/h2&gt;&lt;p&gt;I started by flashing a copy of Ubuntu to a flash drive and booting it. There are plenty of tutorials on the internet about how to boot Ubuntu from a flash drive, so I&amp;#39;ll forgo those instructions here.&lt;/p&gt;&lt;p&gt;The first thing I did was use gparted to create a new partition which will serve as our dedicated boot partition. Since the hard drive is already formatted, doing this requires shrinking the main partition and shifting it 256MB over. This frees up space at the start of the hard drive which can then be formatted into the new dedicated boot partition. If you&amp;#39;ve never used gparted before, I recommend using the GUI version since it&amp;#39;s pretty intuitive. The new partition can be formatted to &amp;quot;ext4&amp;quot; and needs to have the &amp;quot;boot&amp;quot; flag enabled. Completing the shift will take awhile, so you&amp;#39;ll probably want to do this overnight.&lt;/p&gt;&lt;p&gt;Once the new partition has been created, we next need to copy the existing &amp;quot;/boot&amp;quot; directory&amp;#39;s contents over to the new partition. This can be done by mounting the two partitions while still in the Ubuntu Live USB. In the following commands, sda2 is my main partition and sda4 is the new boot partition:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo-s
mkdir/mnt/sda2
mkdir/mnt/sda4
mount/dev/sda2/mnt/sda2
mount/dev/sda4/mnt/sda4
cp-R/mnt/sda2/boot/*/mnt/sda4/
rm-rf/mnt/sda2/boot/
mkdir/mnt/sda2/boot
umount/mnt/sda2
umount/mnt/sda4&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, Linux and Grub need to be reconfigured so they know that the &amp;quot;/boot&amp;quot; directory is now in a separate partition. This can be done manually by modifying Grub&amp;#39;s &amp;quot;grub.cfg&amp;quot; file and Linux&amp;#39;s &amp;quot;/etc/fstab&amp;quot; file, but for simplicity, you can use &lt;a href=&quot;https://help.ubuntu.com/community/Boot-Repair&quot;&gt;Boot Repair&lt;/a&gt;. If you choose to go the Boot Repair route, make sure to switch the GUI into advance mode and go through all the options. Specifically, you need to make sure the &amp;quot;boot partition&amp;quot; option is set to your new boot partition and the &amp;quot;main operating system&amp;quot;&amp;quot; option is set to your main partition. Also, make sure the &amp;quot;set boot flag&amp;quot; option is pointed at your new boot partition and you can save a lot of time by disabling the &amp;quot;check filesystem for errors&amp;quot; option. If you instead decide to go the manual route, you&amp;#39;ll need to manually edit &amp;quot;grub.cfg&amp;quot; looking for every &amp;quot;hd&amp;quot; reference and changing it to point at the correct partitions and the fstab file will need an additional entry to mount your new partition at start-up to the &amp;quot;/boot&amp;quot; directory.&lt;/p&gt;&lt;p&gt;If you do everything correctly, this should fix your Linux system and prevent similar issues from arising in the future.&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Even though modern Linux installers do not require you to create a separate partition for the boot files, I recommend doing it anyway, especially if you have large hard drives. Otherwise, you might run into the problem I did.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Installing psad on Raspberry Pi Running Arch Linux - Carter Yagemann</title>
<link>https://carteryagemann.com/psad-on-pi.html</link>
<guid isPermaLink="false">5E3lH67uNMKcXpCVLI-5FJmh6gunwRiMgab5yQ==</guid>
<pubDate>Tue, 06 Oct 2026 22:43:23 +0000</pubDate>
<description>I&#39;ve been fooling around with IDS and specifically psad and I thought it would be fun to try installing psad on my raspberry pi. Little did I know, installing psad on an ARM processor running Arch Linux with systemd is not a simple process. It took me great effort to …</description>
<content:encoded>&lt;p&gt;I&amp;#39;ve been fooling around with IDS and specifically psad and I thought it would be fun to try installing psad on my raspberry pi. Little did I know, installing psad on an ARM processor running Arch Linux with systemd is not a simple process. It took me great effort to get psad running correctly, so I thought I&amp;#39;d take the time to document my struggles in the hopes that this will be useful to someone else.&lt;/p&gt;&lt;h1&gt;What is psad?&lt;/h1&gt;&lt;p&gt;psad is an intrusion detection system (IDS) which works by monitoring logs generated by iptables (a network firewall common to most Linux distros). You can find more information on psad &lt;a href=&quot;http://cipherdyne.org/psad/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;h1&gt;Scope of this document&lt;/h1&gt;&lt;p&gt;The focus of this document is on challenges I ran into while trying to get psad to install and run on a raspberry pi and my solutions. This document does not cover how to configure or use psad. It &lt;em&gt;does&lt;/em&gt; cover things which I had to taken into consideration due to the raspberry pi CPU being an ARM processor and due to my OS being Arch Linux with systemd.&lt;/p&gt;&lt;h1&gt;Contact&lt;/h1&gt;&lt;p&gt;Many of my solutions are hacks and probably suboptimal hacks at that. If you see anything wrong with this guide or have better solutions to the problems I covered here, feel free to contact me at &lt;a href=&quot;mailto:cmyagema@syr.edu&quot;&gt;cmyagema@syr.edu&lt;/a&gt;.&lt;/p&gt;&lt;h1&gt;Other Useful Resources&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://cipherdyne.org/psad/&quot;&gt;psad homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;An installation guide that helped me &lt;em&gt;(Edit: This blog no longer exists)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-use-psad-to-detect-network-intrusion-attempts-on-an-ubuntu-vps&quot;&gt;A guide on configuring psad&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;h1&gt;Installing psad for ARM from AUR&lt;/h1&gt;&lt;p&gt;Since psad is not included in the main Arch Linux repositories, it has to be downloaded, compiled, and built from the AUR repository.&lt;/p&gt;&lt;p&gt;First, create a file (I will name it &amp;quot;list.txt&amp;quot;) and write in it the following URLs:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;https://aur.archlinux.org/packages/pe/perl-unix-syslog/perl-unix-syslog.tar.gz
https://aur.archlinux.org/packages/pe/perl-iptables-parse/perl-iptables-parse.tar.gz
https://aur.archlinux.org/packages/pe/perl-iptables-chainmgr/perl-iptables-chainmgr.tar.gz
https://aur.archlinux.org/packages/ps/psad/psad.tar.gz&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These are the tarballs which we will need from AUR.&lt;/p&gt;&lt;p&gt;Next, run the following commands to untar the tarballs, build them, and install them:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;cat list.txt | xargs wget
tar xzvf perl-iptables-parse.tar.gz
cd perl-iptables-parse
makepkg -Acs
sudo pacman -U perl-iptables-parse-1.1-2-any.pkg.tar.xz
cd ..
tar xzvf perl-unix-syslog.tar.gz
cd perl-unix-syslog
makepkg -Acs
sudo pacman -U perl-unix-syslog-1.1-4-any.pkg.tar.xz
cd ..
tar xzvf perl-iptables-chainmgr.tar.gz
cd perl-iptables-chainmgr
makepkg -Acs
sudo pacman -U perl-iptables-chainmgr-1.2-2-any.pkg.tar.xz
cd ..
tar xzvf psad.tar.gz
cd psad
makepkg -Acs
sudo pacman -U --force psad-2.2.3-1-armv6h.pkg.tar.xz&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now if you are lucky, unlike me, this should be all you have to do. However, I ran into many additional problems which is what I will focus on in the next section.&lt;/p&gt;&lt;h1&gt;Configuration&lt;/h1&gt;&lt;p&gt;As I mentioned earlier, I am not going to cover how to configure psad. There is, however, one configuration which I will mention because it&amp;#39;s different from other systems. Namely, the location for syslog is in an usual location because of how systemd logs.&lt;/p&gt;&lt;p&gt;To fix this setting, list the contents of your &lt;code&gt;/var/log/journal/&lt;/code&gt; directory. You should see a directory containing a bunch of letters and numbers and inside that directory should be a file called &lt;code&gt;system.journal&lt;/code&gt;. I found that this is the file which psad has to be pointed to.&lt;/p&gt;&lt;p&gt;Once you have identified this path, open &lt;code&gt;/etc/psad/psad.conf&lt;/code&gt; and point &lt;code&gt;IPT_SYSLOG_FILE&lt;/code&gt; to this file. In my case, this means:&lt;/p&gt;&lt;p&gt;If you want to try port scanning yourself or in general test your psad installation, be mindful that the raspberry pi has very limited computing resources so it might take awhile for your test to reflect in psad&amp;#39;s status.&lt;/p&gt;&lt;h2&gt;Troubleshooting&lt;/h2&gt;&lt;h3&gt;wget fails due to certificates&lt;/h3&gt;&lt;p&gt;This one is easy, just replace the &lt;code&gt;cat link | xargs wget&lt;/code&gt; with &lt;code&gt;cat link | xargs wget --no-check-certificate&lt;/code&gt;.&lt;/p&gt;&lt;h3&gt;makepkg fails and returns a build error&lt;/h3&gt;&lt;p&gt;Try rebooting the raspberry pi. Sometimes not having enough memory can cause the build to fail.&lt;/p&gt;&lt;h3&gt;psad is installed, but when I run &lt;code&gt;sudo psad -S&lt;/code&gt; I get the message &lt;code&gt;pid file [...]/psadwatchd.pid does not exist&lt;/code&gt;&lt;/h3&gt;&lt;p&gt;If you&amp;#39;re seeing this towards the top of the output for &lt;code&gt;sudo psad -S&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;[-] psad: pid file /var/run/psad/psadwatchd.pid does not exist for psadwatchd on HOSTNAME&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then you probably have the same problem I had.&lt;/p&gt;&lt;p&gt;This was the most painful of the problems I ran into and this was the problem which was big enough to convince me to write this document. If I hadn&amp;#39;t ran into this issue (and the systemd logging issue), I wouldn&amp;#39;t have bothered writing any of this. The problem in my case was &amp;quot;psadwatchd&amp;quot; wasn&amp;#39;t starting for some reason when &amp;quot;psad&amp;quot; started. To confirm this as the source of the problem, run:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;ps -A | grep &amp;quot;psad&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you only see one process called &amp;quot;psad&amp;quot; and no &amp;quot;psadwatchd&amp;quot;, then you&amp;#39;re having the same problem as me.&lt;/p&gt;&lt;p&gt;The solution I came up for this is very much a hack, but it works decently. Basically, I got around this by making a separate service for psadwatchd.&lt;/p&gt;&lt;p&gt;First, create a new file: &lt;code&gt;/etc/systemd/system/psadwatchd.service&lt;/code&gt;&lt;/p&gt;&lt;p&gt;In this file, write:&lt;/p&gt;&lt;p&gt;Next, confirm that you wrote this service file correctly by starting it in systemctl:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl start psadwatchd&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If all went as it should, you should be able to execute the following two commands:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;ps -A | grep &amp;quot;psad&amp;quot;
sudo psad -S&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first command should return both a &lt;code&gt;psad&lt;/code&gt; process and a &lt;code&gt;psadwatchd&lt;/code&gt; process. The second command should now show information on psadwatchd and no longer show an error about missing PID files.&lt;/p&gt;&lt;p&gt;Now that you&amp;#39;ve made a working psadwatchd service file, add this new service to systemd&amp;#39;s startup list:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;sudo systemctl enable psadwatchd&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that should be it (hopefully).&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Last rites for Gentoo&#39;s Chromium package [LWN.net]</title>
<link>https://lwn.net/SubscriberLink/1097760/2be4d9e3eeb59039/</link>
<guid isPermaLink="false">ET74k9PtVCw9i1MmXuf_Gfu4kxtw5f3YAHXKjg==</guid>
<pubDate>Tue, 06 Oct 2026 22:42:59 +0000</pubDate>
<description>Chromium, the open-source upstream project for Google&#39;s Chrome web browser, is the browser of c [...]</description>
<content:encoded>&lt;summary&gt;&lt;h3&gt;Firefox maintenance&lt;/h3&gt;
      &lt;div&gt;
      &lt;p&gt; Posted Oct 6, 2026 18:03 UTC (Tue)
                               by &lt;b&gt;sam_c&lt;/b&gt; (subscriber, #139836)
                              [&lt;a href=&quot;https://lwn.net/Articles/1099030/&quot;&gt;Link&lt;/a&gt;] 
      &lt;/p&gt;
      
      &lt;/div&gt;
      &lt;/summary&gt;&lt;p&gt;I was under the impression (I think wrongly?) that anonymous comments could be made with subscription links but it looks like not.&lt;/p&gt;&lt;p&gt;Posting juippis&amp;#39;s comment on his behalf then:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Hey, sam asked me to fill in as Gentoo&amp;#39;s current Firefox maintainer. Firefox is a lot of work, but I&amp;#39;d like to share few points why I believe it&amp;#39;s easier  than Chromium. Note that I have close to 0 experience packaging Chromium, I&amp;#39;ve just aided with some updates previously.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;I could write a long detailed post about everything I do with each Firefox release, but since I&amp;#39;m a guest here, I&amp;#39;ll try to keep it short.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;TLDR as a whole is:&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;Doing the version bumps properly takes a lot of time - mostly because I test with multiple USE flag combinations, gcc/clang, and simply testing pgo itself takes like an hour to build once. It can be hard, because Gentoo carries few custom patches, e.g. to enable different system-* libraries to be used instead of bundled ones, and those regularly break / need patch rebasing. But upstream is rather welcoming, and bigger issues affecting the whole Linux ecology are usually fixed fast by upstream. Upstream also has a CI building using Ubuntu. We usually find toolchain / system-lib related issues amongst the first ones due to the nature of Gentoo being a rolling-release distro, with newer toolchain available. Some of the Firefox developers seem to use Gentoo, too. Therefore I&amp;#39;d say the relations between upstream and other distros is stronger with Firefox, especially since Firefox is often the default browser in other distributions.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;Gentoo offers &amp;quot;two channels&amp;quot; - Firefox-157.0 with testing keywords, and Firefox-153.4.0esr with stable keywords. Thunderbird is identical; Thunderbird-157.0 and Thunderbird-153.4.0esr. Thunderbird releases come immediately after Firefox and sometimes requires TB-specific patches to be added. Firefox recently switched to 2-week release cadence, where it used to be 4 weeks, so the work is now doubled each month. It currently takes me ~20 hours every 2 weeks to do everything related to version bumps (both Firefoxes, both Thunderbirds, Spidermonkey, security bugs...) and I&amp;#39;ve even skipped a step recently, and am pushing ESR&amp;#39;s straight-to-stable (after testing on stable system) to save some time. Most of the hours go into running build-tests, which can be done by leaving the pc to run on its own. There&amp;#39;s I&amp;#39;d guess ~3-4 hours of &amp;quot;active&amp;quot; work (without bugs) whenever major releases happen. So there&amp;#39;s one less active channel to monitor than what Chromium currently has, but I think handling Thunderbirds make it equal here.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;Gentoo also offers different variety outside use flags: you have musl, libcxx, different architechtures (arm, x86, riscv) that all require their own quirks. Luckily the power users with these setups know to provide patches, which I then test on glibc and add them if it&amp;#39;s ok. Any rust-related issues are somewhat hard to debug, and you can bet there&amp;#39;s plenty. Chromium has similar challenges there, but I&amp;#39;d say the nature of Chromium&amp;#39;s bundled toolchain vs. system toolchain makes it harder for everyone even with &amp;quot;normal&amp;quot; setup.&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;Overall Firefox takes a lot less time to build than Chromium which makes it more bearable. And as sam said, the build system changes affecting us between major releases are usually rather minimal. As the sole Firefox maintainer in Gentoo, I also do feel like there&amp;#39;s a bit more community support for Firefox. Often times when a bug for Firefox in Gentoo is filed, I&amp;#39;m not even the first one to reply there. And through collaboration there&amp;#39;s been cases where we discovered a bug in GCC directly, which was then fixed in GCC (by GCC developer sam) :)&lt;/p&gt;
&lt;/blockquote&gt;&lt;div&gt;
            
            
            
          &lt;/div&gt;&lt;p&gt;
     
    &lt;/p&gt;</content:encoded>
</item>
<item>
<title>Janet on x32: 32-bit Pointers, 64-bit Speed, 25% Less RAM | Alex Alejandre</title>
<link>https://alexalejandre.com/programming/lisp/janet-for-the-x32-abi/</link>
<guid isPermaLink="false">UtWvfZOpUoxpyZxXmKgwI6TTDxlggKl24rSolw==</guid>
<pubDate>Tue, 06 Oct 2026 22:42:59 +0000</pubDate>
<description>RAM&#39;s expensive again. Can existing software run faster with 50% less RAM via an unloved compiler flag?</description>
<content:encoded>&lt;summary&gt;See the Scripts and Results&lt;/summary&gt;&lt;p&gt;This is on cachyos (arch, btw) with lib32-glibc lib32-gcc-libs. Adding this to a build script forces libraires like spork to build at 32 bit too!&lt;/p&gt;&lt;p&gt;For &lt;code&gt;mem.janet&lt;/code&gt;:&lt;/p&gt;&lt;p&gt;Note, these use Fish and I don’t want to rebuild my site with other language support:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo pacman -S time # different from just time
command time -v ./bin/janet mem.janet # command skips the fish version
command time -v ./janet32/bin/janet mem.janet

2000000
       Command being timed: &amp;quot;./bin/janet mem.janet&amp;quot;
       User time (seconds): 0.24
       System time (seconds): 0.05
       Percent of CPU this job got: 100%
       Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.30
       Average shared text size (kbytes): 0
       Average unshared data size (kbytes): 0
       Average stack size (kbytes): 0
       Average total size (kbytes): 0
       Maximum resident set size (kbytes): 145196
       Average resident set size (kbytes): 0
       Major (requiring I/O) page faults: 0
       Minor (reclaiming a frame) page faults: 33513
       Voluntary context switches: 1
       Involuntary context switches: 9

2000000
       Command being timed: &amp;quot;./janet32/bin/janet mem.janet&amp;quot;
       User time (seconds): 0.47
       System time (seconds): 0.03
       Percent of CPU this job got: 99%
       Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.50
       Average shared text size (kbytes): 0
       Average unshared data size (kbytes): 0
       Average stack size (kbytes): 0
       Average total size (kbytes): 0
       Maximum resident set size (kbytes): 113716
       Average resident set size (kbytes): 0
       Major (requiring I/O) page faults: 0
       Minor (reclaiming a frame) page faults: 25686
       Voluntary context switches: 1
       Involuntary context switches: 21&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I added a 0 in the test&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;command time -v ./bin/janet mem.janet
                  command time -v ./janet32/bin/janet mem.janet
20000000
        Command being timed: &amp;quot;./bin/janet mem.janet&amp;quot;
        User time (seconds): 2.83
        System time (seconds): 0.46
        Percent of CPU this job got: 99%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.31
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 1410668
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 316820
        Voluntary context switches: 1
        Involuntary context switches: 164
        Exit status: 0
20000000
        Command being timed: &amp;quot;./janet32/bin/janet mem.janet&amp;quot;
        User time (seconds): 4.64
        System time (seconds): 0.35
        Percent of CPU this job got: 99%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:05.00
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 1098372
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 238633
        Voluntary context switches: 1
        Involuntary context switches: 193&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For e.g. &lt;code&gt;declarative-dsls/tests.janet&lt;/code&gt;&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;98 passed
        Command being timed: &amp;quot;./bin/janet ./lib/janet/bin/judge declarative-dsls/tests.janet&amp;quot;
        User time (seconds): 0.42
        System time (seconds): 0.02
        Percent of CPU this job got: 100%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.45
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 61900
declarative-dsls/tests.janet

98 passed
        Command being timed: &amp;quot;./bin/janet ./lib/janet/bin/judge declarative-dsls/tests.janet&amp;quot;
        User time (seconds): 0.70
        System time (seconds): 0.02
        Percent of CPU this job got: 99%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.72
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 54108
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 0
        Minor (reclaiming a frame) page faults: 12735&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded>
</item>
<item>
<title>The Hopefully Eventually Ultimate Desktop Linux Troubleshooting Guide: Recovering from Crashes and Freezes</title>
<link>https://www.autodidacts.io/troubleshooting-desktop-linux-crashes-and-freezes/</link>
<guid isPermaLink="false">IHEqQufbgtpNvnOCS6SBafE7PseQ0QbslrGFjQ==</guid>
<pubDate>Tue, 06 Oct 2026 16:54:48 +0000</pubDate>
<description>Free advice from the printer fixer</description>
<content:encoded>&lt;small&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;/b&gt; this post is part of &lt;a href=&quot;https://www.autodidacts.io/100daystooffload/&quot;&gt;#100DaysToOffload&lt;/a&gt;, a challenge to publish 100 posts in 365 days. These posts are generally shorter and less polished than our normal posts; expect typos and unfiltered thoughts! &lt;a href=&quot;https://www.autodidacts.io/tag/100daystooffload/&quot;&gt;View more posts in this series.&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/small&gt;&lt;br/&gt;&lt;img src=&quot;https://www.autodidacts.io/content/images/2026/08/The_Scream_Pastel.jpg&quot; alt=&quot;The Hopefully Eventually Ultimate Desktop Linux Troubleshooting Guide: Recovering from Crashes and Freezes&quot; title=&quot;&quot;/&gt;&lt;p&gt;I&amp;#39;ve been using Linux as my main/only operating system for my entire life. While I would like to brag that Linux is more stable than Mac, the simple fact is that it isn’t. This is sad, because it’s great in every other way, and the bugs are mostly fairly surface-level, yet give it a patchy reputation among normal users.&lt;/p&gt;&lt;figure&gt;&lt;img src=&quot;https://www.autodidacts.io/content/images/2026/08/The_Scream_Pastel-1.jpg&quot; alt=&quot;The Hopefully Eventually Ultimate Desktop Linux Troubleshooting Guide: Recovering from Crashes and Freezes&quot; title=&quot;&quot;/&gt;&lt;figcaption&gt;&lt;span&gt;“Oh no! That &lt;/span&gt;&lt;i&gt;&lt;em&gt;Was&lt;/em&gt;&lt;/i&gt;&lt;span&gt; The Backup…”, ¬Oil on ¬Canvas&lt;/span&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Because I spend a lot of time in the terminal, and all my friends also run Linux, I often get called in to help when their systems have issues. Often, I fail to solve the problem, which is frustrating. So over the past few years I have taken some time to learn more about recovering from all the issues that need recovering from, and collecting my techniques. Here are some of the most useful tools and approaches I have found.&lt;/p&gt;&lt;p&gt;Over the years, I have used Knoppix, Ubuntu, Linux Mint, Manjaro, NetBSD, OpenBSD, and others. These tips are mostly for Ubuntu, Linux Mint, and other Debian-based distros. I have used Xfce, Compiz, CWM, Cinnamon, Sway, Mate, and Gnome. These are mostly about Gnome and Cinnamon.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Note: this article is a living document that I intend to add to as I learn more and have more time. If you have a specific problem, write in or drop a comment, and I will prioritize that section.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;This post pairs well with the more high-level advice in &lt;a href=&quot;https://www.autodidacts.io/troubleshooting/&quot;&gt;&lt;em&gt;Troubleshooting: A Skill That Never Goes Obsolete&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h3&gt;If a program has crashed&lt;/h3&gt;&lt;p&gt;&lt;code&gt;killall PROGRAM_NAME&lt;/code&gt; (usually, &lt;code&gt;killall firefox&lt;/code&gt;)&lt;/p&gt;&lt;h3&gt;Scary black screen&lt;/h3&gt;&lt;p&gt;If all you see is text, there&amp;#39;s a goodish chance that it’s a problem with the graphics drivers. Try re-installing them. If you&amp;#39;re using the proprietary Nvidia drivers (which are a nightmare in my experience) try using the open Nouveau driver. Also try switching to a different Nvidia driver if one is available. Also, try fully purging and re-installing Nvidia drivers. If you&amp;#39;re using the Nouveau driver, try switching to Nvidia drivers. If you&amp;#39;re using Xorg, try switching to Wayland. If you&amp;#39;re using Wayland, try switching to Xorg.&lt;/p&gt;&lt;pre&gt;&lt;code&gt;sudo apt purge *nvidia* # potentially dangerous
sudo ubuntu-drivers install # follow prompts&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you’re using a Macbook, &lt;em&gt;good luck&lt;/em&gt;. In my experience, despite what everyone says, Macbooks have some of the worst Linux support. The four Macbooks I’ve encountered that were running Linux were all unmitigated problem cases, and graphics drivers were the weakest point. Once I spent seven hours getting a friend’s Macbook back to graphical functionality after an Ubuntu upgrade. I breathe a sigh of relief when Macbooks finally conk for good, and ardently recommend the owner upgrade to a ThinkPad if they want me to keep doing tech support.&lt;/p&gt;&lt;p&gt;Google the issue + the model of your laptop. Often you can edit &lt;code&gt;/etc/default/grub&lt;/code&gt; and add something to the &lt;code&gt;GRUB_CMDLINE_LINUX_DEFAULT=...&lt;/code&gt; line. Often that something is &lt;code&gt;nomodeset&lt;/code&gt;. This is also often how I fix issues with screen brightness and backlight.&lt;/p&gt;&lt;p&gt;Once you get back to functionality, you can try to figure out &lt;em&gt;why &lt;/em&gt;the specific configuration you had before broke, by looking in the logs. Or if you&amp;#39;re happy with the new config, just forget about it and use what works.&lt;/p&gt;&lt;h3&gt;If the mouse slows down and gets jittery, and the fans rev up, and the I/O light blinks fast or goes solid, and then the system fully freezes&lt;/h3&gt;&lt;p&gt;This usually means that:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Somebody opened too many tabs in Firefox (likely something JavaScript heavy like Reddit, YouTube, or Facebook)&lt;/li&gt;&lt;li&gt;The computer ran out of RAM&lt;/li&gt;&lt;li&gt;It started swapping&lt;/li&gt;&lt;li&gt;Now it’s crashed&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;We can stop this at any point in the chain, but the farther up, the better.&lt;/p&gt;&lt;p&gt;Don’t open so many tabs. Or, use &lt;code&gt;about:unloads&lt;/code&gt; to unload the heaviest tabs when you start to notice slow downs. If you catch it when the mouse starts to lag, &lt;em&gt;immediately&lt;/em&gt; hit alt-f4 to quit the most resource intensive app that won&amp;#39;t lose work (usually your browser), then wait. &lt;strong&gt;Do not press close over and over again: it will just make the computer mad.&lt;/strong&gt; If you manage to get a heavy app closed before the system becomes unresponsive, it will likely recover, and you can take further steps.&lt;/p&gt;&lt;p&gt;You can also start the culprit app (usually a browser or media transcoding workload or LLM) with a systemd memory limit, which generally prevents it from causing this issue. (Or you can try to &lt;code&gt;renice&lt;/code&gt; the app, but this doesn&amp;#39;t seem to be as effective.)&lt;/p&gt;&lt;p&gt;Here’s how to run an app with a 4GB memory limit:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;systemd-run --scope -p MemoryMax=4G --user COMMAND_NAME&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Change COMMAND_NAME to &lt;code&gt;firefox&lt;/code&gt;, &lt;code&gt;ffmpeg&lt;/code&gt;, &lt;code&gt;llama-server&lt;/code&gt;, or whatever is taking the system down with it.)&lt;/p&gt;&lt;p&gt;There’s also ulimit, but I haven&amp;#39;t used it as much.&lt;/p&gt;&lt;p&gt;The simplest fix: BUY MORE RAM. Years ago, going from 8gb to 12gb of RAM on my ThinkPad went from daily seizures of this type to annual seizures. Basically cured!&lt;/p&gt;&lt;p&gt;Bad ram (or badly-seated ram) can also be the culprit.&lt;/p&gt;&lt;p&gt;On servers with limited RAM, adding swap can save the day, but I find that when a desktop Linux system starts swapping, that’s pretty much the end of the good times and the beginning of the bad times. &lt;/p&gt;&lt;p&gt;An SSD might help, because swap speed will be closer to RAM speed. (An SSD is one of the most effective ways to make your computer go faster, other than adding more RAM.)&lt;/p&gt;&lt;p&gt;There are various settings related to swapping behaviour (&amp;quot;swappiness&amp;quot;) and overcommiting memory that &lt;em&gt;may&lt;/em&gt; help (see &lt;a href=&quot;https://news.ycombinator.com/item?id=34395119&amp;amp;ref=autodidacts.io&quot;&gt;here&lt;/a&gt;), but I haven&amp;#39;t actually used them on desktop Linux. &lt;/p&gt;&lt;p&gt;If you don&amp;#39;t manage to get the app closed, try to get to a console. Try: opening a terminal (likely won&amp;#39;t work), alt+f2 (also likely won&amp;#39;t work, because it&amp;#39;s part of the window manager which is crashed), and then dropping to a virtual console with Ctrl+Alt+f2. Press each key slowly, on after the other, holding down the previous keys: the response time is way slower than a normal keyboard. The exact f-key varies: generally Ctrl+Alt+f1 gets you to a login session screen, which you don&amp;#39;t want, and the main session is on Ctrl+Alt+f5 or Ctrl+Alt+f7, so I find that f2 or f3 are most likely to get me to a virtual terminal.&lt;/p&gt;&lt;p&gt;Enter username and password. Now you should be able to run &lt;code&gt;killall firefox&lt;/code&gt; (or ffmpeg, or ollama, or whisper-stream, or whatever it is). You can also inspect what&amp;#39;s crashed with &lt;code&gt;top&lt;/code&gt; or &lt;code&gt;htop&lt;/code&gt;. &lt;code&gt;htop&lt;/code&gt; is good stuff! (and also makes it easy to send stop signals with f9 and then a number; in this case, likely 9) If you can get to the virtual console, you can usually can rescue an out-of-ram freeze caused by a specific app.&lt;/p&gt;&lt;p&gt;But the most powerful technique I&amp;#39;ve found for this is enabling &lt;a href=&quot;https://en.wikipedia.org/wiki/Magic_SysRq_key?ref=autodidacts.io&quot;&gt;Magic System Request keys&lt;/a&gt;, and then using Ctrl+Alt+PrintScr+f at the first sign of trouble to activate the OOM_KILLER to terminate the most resource-intensive process (usually a firefox tab). It works wonders.&lt;/p&gt;&lt;p&gt;Check your current sysrq value with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;cat /proc/sys/kernel/sysrq&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Edit the &lt;code&gt;kernel.sysrq&lt;/code&gt; numerical value in the alphabetically last file listed by this command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ls /etc/sysctl.d/ | xargs -I{} grep -l kernel.sysrq /etc/sysctl.d/&amp;quot;{}&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(After rebooting, check that the value stuck using the previous command.)&lt;/p&gt;&lt;p&gt;Then you can see what it quit with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;dmesg -T | egrep -i &amp;#39;killed process&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;... and hope it wasn’t anything important.&lt;/p&gt;&lt;h3&gt;If it’s the desktop environment that has crashed&lt;/h3&gt;&lt;p&gt;If you’re running Cinnamon (Linux Mint’s default desktop environment), try running this from a virtual console:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;DISPLAY=:0 cinnamon --replace&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you’re using Gnome (on Xorg), you can try these, but I have never managed to restart a Gnome session without it quitting all open apps, and losing data:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;pkill -3 gnome-shell
sudo pkill -9 ^gnome-shell&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If you know how to, let me know!&lt;/p&gt;&lt;h3&gt;If you’re unclear about the difference between a window manager, a desktop environment, a display server, and a distro(bution) are&lt;/h3&gt;&lt;p&gt;I’m a bit fuzzy on this, too! Specifically, the where the line is between a window manager and a desktop environment. But the general stack goes, from low-level to high level:&lt;br/&gt;&lt;br/&gt;Operating System Family (ie, Linux, BSD, Mac, Windows) → Distro (ie, Linux Mint, Ubuntu, NetBSD) → Display Server (X Window System, Wayland) → Desktop Environment (ie, Xfce, Gnome, Cinnamon, KDE) → Window Manager (Compiz, Openbox, Sway, i3) → Theme &amp;amp; Settings (these days I just use the default, but I used to regularly break my system trying to make it look fancy).&lt;/p&gt;&lt;h3&gt;If your screen goes all colorful or develops lines and weird patterns&lt;/h3&gt;&lt;p&gt;If you’re using an external monitor, likely the cable connector isn’t seated correctly, or the contacts are dirty.&lt;/p&gt;&lt;p&gt;If it’s a laptop, it’s most likely an issue with the graphics drivers, or the screen connector. I have had this happen a few times, usually related to  GPU intensive workloads and suspend, but I haven’t found the root cause, because I encounter it so rarely. All I know is that restarting Cinnamon from a virtual console doesn’t help.&lt;/p&gt;&lt;h3&gt;If it has fully crashed and rebooted on its own&lt;/h3&gt;&lt;p&gt;Oof, this is serious. In my experience this is fairly rare. I/O issues on peripherals have caused this in the past (ie, excessive power draw from a dying hard drive). Check the logs for insight. &lt;/p&gt;&lt;h3&gt;Suspend issues&lt;/h3&gt;&lt;p&gt;These often have to do with the graphics drivers, and the specific hardware. Sometimes adding grub command line options helps. Often changing drivers helps.&lt;/p&gt;&lt;h3&gt;If you want to know what a program is &lt;em&gt;doing&lt;/em&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo strace -p$(pidof firefox) -e trace=write -s1000 -fp 18386 2&amp;gt;&amp;amp;1 | grep -o &amp;#39;&amp;quot;.\+[^&amp;quot;]&amp;quot;&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(replace &lt;code&gt;firefox&lt;/code&gt; with the name of the program you want to know about)&lt;/p&gt;&lt;p&gt;If a program has a bug, this is useful for viewing the error message / stack trace, without quitting the program and re-running it from terminal.&lt;/p&gt;&lt;h3&gt;If you want to know what is hogging all the resources&lt;/h3&gt;&lt;p&gt;My go-to is the wonderful &lt;code&gt;htop&lt;/code&gt;. &lt;code&gt;top&lt;/code&gt; is installed by default. &lt;code&gt;glances&lt;/code&gt; and &lt;code&gt;btop&lt;/code&gt; can also be helpful.&lt;/p&gt;&lt;p&gt;For figuring out suspiciously heavy network or disk write activity, try &lt;code&gt;iotop&lt;/code&gt; and &lt;code&gt;nethogs&lt;/code&gt;. Also, &lt;code&gt;powertop&lt;/code&gt;, if you want to tune battery life.&lt;/p&gt;&lt;h3&gt;If you want to know whether a script actually quit or crashed and left pieces churning along in the background&lt;/h3&gt;&lt;p&gt;Run &lt;code&gt;htop&lt;/code&gt; and search with f3. I often find that a script called some process, then crashed, and left a heavy process still running. This mostly happens when you&amp;#39;re developing (ie, for me, Bash/Python scripts that called Whisper C++ or Selenium), or using really bad quality software. Also, viruses.&lt;/p&gt;&lt;h3&gt;If you&amp;#39;re stuck in Vim&lt;/h3&gt;&lt;p&gt;&lt;code&gt;:q!&lt;/code&gt;&lt;/p&gt;&lt;h3&gt;If the screen is black&lt;/h3&gt;&lt;p&gt;Is the backlight on? &lt;/p&gt;&lt;p&gt;Try plugging in an external monitor. This will tell you whether it&amp;#39;s your graphics drivers, or hardware.&lt;/p&gt;&lt;p&gt;If external monitor works, it could be your backlight (common), or your screen connector. (These are both pretty easy to fix if you have a repairable laptop like a thinkpad.) Or, it could be the LCD panel itself.&lt;/p&gt;&lt;p&gt;It also could be a hardware/driver issue that can be fixed with the grub command line options.&lt;/p&gt;&lt;h3&gt;If the Wifi doesn&amp;#39;t work&lt;/h3&gt;&lt;p&gt;Try wired internet. If it doesn’t work either, the problem isn’t the Wifi drivers.&lt;/p&gt;&lt;p&gt;Make sure you can get internet from the network on a different device.&lt;/p&gt;&lt;p&gt;Check what the output of &lt;code&gt;ifconfig&lt;/code&gt; looks like.&lt;/p&gt;&lt;p&gt;Try running &lt;code&gt;sudo service NetworkManager restart&lt;/code&gt; (fixes it surprisingly often!)&lt;/p&gt;&lt;h3&gt;If your WiFi hotspot has no internet in it&lt;/h3&gt;&lt;p&gt;Maybe it’s your VPN, or firewall. But in my case, it was broadcasting on channel 13, which is only supported in Japan. &lt;br/&gt;&lt;br/&gt;I was able to fix it with:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;nmcli con modify &amp;quot;Hotspot&amp;quot; 802-11-wireless.band bg # band must be set. Options, in my case, were &amp;quot;a&amp;quot; and &amp;quot;bg&amp;quot;. I do not know the difference, but &amp;quot;bg&amp;quot; worked.
nmcli con modify &amp;quot;Hotspot&amp;quot; 802-11-wireless.channel 6 # set the channel
nmcli con up &amp;quot;Hotspot&amp;quot; # bring it up&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;(Change &amp;quot;Hotspot&amp;quot; to your network name or UUID.)&lt;/p&gt;&lt;h3&gt;If the printer won’t print&lt;/h3&gt;&lt;p&gt;Try rebooting the printer.&lt;/p&gt;&lt;p&gt;Try a different USB port!&lt;/p&gt;&lt;p&gt;Try clearing the print queue and re-sending the job (very often works!)&lt;/p&gt;&lt;p&gt;Make sure you sent it to the right printer (there are often multiple entries for the same printer, only one of which works.)&lt;/p&gt;&lt;p&gt;Try running &lt;code&gt;sudo service cups restart&lt;/code&gt;. This works quite often.&lt;/p&gt;&lt;h3&gt;If your mouse or touchpad has stopped moving&lt;/h3&gt;&lt;p&gt;Open terminal and run this command to reload the drivers:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo modprobe -r psmouse &amp;amp;&amp;amp; sudo modprobe psmouse&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This usually fixes it.&lt;/p&gt;&lt;p&gt;If it doesn’t: try switching to Synaptics drivers if you’re using libinput drivers, and to libinput drivers if you’re using Synaptics drivers.&lt;/p&gt;&lt;h3&gt;If you&amp;#39;re having trouble installing software&lt;/h3&gt;&lt;p&gt;Try running &lt;code&gt;sudo apt update&lt;/code&gt; to make sure you have up-to-date package cache. Look at the error message when you run &lt;code&gt;sudo apt upgrade&lt;/code&gt; or &lt;code&gt;sudo apt install PACKAGE_NAME_HERE&lt;/code&gt;. The error messages here are often more helpful than the ones you get from the GUI.&lt;/p&gt;&lt;p&gt;Remove old PPAs etc that you don&amp;#39;t need any more.&lt;/p&gt;&lt;p&gt;Try running &lt;code&gt;sudo apt install --fix-missing&lt;/code&gt;; this usually fixes it.&lt;/p&gt;&lt;p&gt;If an app installed with snap has mysteriously disappeared, it might be in the process of being updated.&lt;/p&gt;&lt;h3&gt;If you get Error Splicing File errors&lt;/h3&gt;&lt;p&gt;Your external media or internal HDD are likely full! This is a terrifying situation that happens all the time. Many things will cease to function, because they require &lt;code&gt;tmp&lt;/code&gt; space, even things that you would expect to keep working.&lt;/p&gt;&lt;p&gt;Find out if your internal root disk is full with:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;df -h /&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here are some commands for finding big files that you might be able to delete:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;du -a 2&amp;gt;/dev/null | sort -n -r

du --max-depth=1 /path | sort -r -k1,1n

find /home -type f -exec du -s {} \; | sort -r -k1,1n | head

du -a -h /path | sort -h -r | head -n 10&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At the time of writing, my 1TB internal drive is 100% full, with 7gb free. Wish me luck!&lt;/p&gt;&lt;h3&gt;If the issue is with external media (thumbdrive, HDD)&lt;/h3&gt;&lt;p&gt;If it doesn&amp;#39;t show up in file manager, check in Gnome Disks; if it doesn&amp;#39;t show up there, check in the logs (and also try it on a different computer, and a different USB port, and try a known-good flashdrive/HDD on the computer in the same USB port to isolate the problem).&lt;/p&gt;&lt;p&gt;Errors tend to show up in dmesg. Grep for the manufacturer name (ie &lt;code&gt;ADATA&lt;/code&gt;), or for &lt;code&gt;usb&lt;/code&gt; or &lt;code&gt;device&lt;/code&gt;. Sometimes the actual device is rebranded, so it will say one thing, but will show up as a bigger manufacturer (often Toshiba). &lt;/p&gt;&lt;p&gt;This will help get the /dev/sdX, and then you can go from there. &lt;/p&gt;&lt;h3&gt;If a SD card / flashdrive got corrupted&lt;/h3&gt;&lt;p&gt;If it is critical, take it to a specialist. This will cost a bundle. Otherwise:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Create a disk image with &lt;code&gt;ddrescue&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Do all further operations on a &lt;em&gt;copy&lt;/em&gt; of the disk image, not on the disk image, and definitely not on the device itself (read/write intensive operations might damage it more)&lt;/li&gt;&lt;li&gt;Use fsck to repair corrupted file systems. Often it works. (It sometimes leaves garbage fragments of deleted files.)&lt;/li&gt;&lt;li&gt;Use photorec to recover photos and videos that fsck can&amp;#39;t recover&lt;/li&gt;&lt;li&gt;Use untrunc to piece back together corrupted videos (as long as you have a good video from the same camera)&lt;/li&gt;&lt;li&gt;^^^ these two tools can save rashers and rashers of bacon. Consider donating to the maintainers (and also, the bloggers who told you about them)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Free advice: never buy no-name-brand ultra-good-price storage from Ebay or Amazon. Never. When it comes to storage, cheap can be very, very expensive.&lt;/p&gt;&lt;h2&gt;Check the logs&lt;/h2&gt;&lt;p&gt;The logs are the troubleshooter’s best friend. On Linux, the good stuff is mostly in /var/log&lt;/p&gt;&lt;p&gt;There, you will likely find logs for all kinds of things. The most interesting ones:&lt;/p&gt;&lt;p&gt;dmesg (includes peripherals, startup stuff. #1 stop)&lt;/p&gt;&lt;p&gt;syslog (#2 stop)&lt;/p&gt;&lt;p&gt;kern.log (kernel stuff, obviously)&lt;/p&gt;&lt;p&gt;Xorg.log (X Window System)&lt;/p&gt;&lt;p&gt;Probably there will be multiple files for each log, because logs are rotated. So you&amp;#39;ll have dmesg, dmesg.0, dmesg.1.gz, dmesg.2.gz, etc, etc.&lt;/p&gt;&lt;p&gt;Five ways to view a log:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;code&gt;cat filename&lt;/code&gt; (print whole thing to console. most basic)&lt;/li&gt;&lt;li&gt;open in a text editor &lt;code&gt;vim filename&lt;/code&gt;. Useful for searching, reading at leisure, filtering, etc. Some text editors will choke on very large files (gedit, for example). Vim is pretty good at opening gigantic text files.&lt;/li&gt;&lt;li&gt;view top of bottom part with tail or head (ie, &lt;code&gt;tail -n 10 filename&lt;/code&gt; to view last ten lines), or watch a file live with &lt;code&gt;tail -f filename&lt;/code&gt;, then do the thing that might cause the error message, and see what gets output.&lt;/li&gt;&lt;li&gt;search in a file &lt;code&gt;grep -i fail syslog&lt;/code&gt; or in the whole log directory (which tends to be slow) &lt;code&gt;grep -i fail&lt;/code&gt;&lt;/li&gt;&lt;li&gt;journalctl is the fancy new thing that I don&amp;#39;t really know how to use. It&amp;#39;s supposedly great. Try it with &lt;code&gt;journalctl -u cron&lt;/code&gt; or &lt;code&gt;journalctl --since=-1hour&lt;/code&gt;. It can filter by process ID, executable name, date (including since-last-boot), urgency, and more&lt;/li&gt;&lt;li&gt;Bonus option: print it out on a thousand sheets of paper like a real hacker and then inspect it with a magnifying glass&lt;/li&gt;&lt;/ol&gt;&lt;hr/&gt;&lt;p&gt;The main things I do:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Just browse through all the logs and look for something that looks suspicious, or related to the problem&lt;/li&gt;&lt;li&gt;Tail the most-likely-to-be-relevant log with &lt;code&gt;-f&lt;/code&gt; (follow) and then do the thing that triggers the bug and see what comes out of the log (very effective if the bug is reproducible, ie, an external drive won&amp;#39;t mount, or a program crashes on startup)&lt;/li&gt;&lt;li&gt;Explicitly grep for error messages. These can take several forms. Sometimes it says Error, and sometimes it says Err: ... sometimes it says Failure to X and sometimes it says Failed to start Y. Other watchwords are &amp;quot;segfault&amp;quot;, &amp;quot;panic&amp;quot;, &amp;quot;fatal&amp;quot;, &amp;quot;crash&amp;quot;, (core) &amp;quot;dumped&amp;quot;. You can find them all with:&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;grep -i -E &amp;quot;fail|fatal|err|panic|segfault|segmentation fault|dumped|core dumped|killed|warn|bad&amp;quot; syslog # grep case insensitive with extended regex for any of the following&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Befriend the terminal&lt;/h3&gt;&lt;p&gt;You won&amp;#39;t get far troubleshooting Linux crashes without getting used to running commands.&lt;/p&gt;&lt;p&gt;Command history (up arrow) and completion (tab) and reverse history search (ctrl+r) and copying-and-pasting (ctrl+shift+c and ctrl+shift+v instead of ctrl+c and ctrl+v) are essential.&lt;/p&gt;&lt;p&gt;Also, normal keystrokes like Ctrl+Z and Ctrl+S do weird things in the terminal. Avoid.&lt;/p&gt;&lt;h3&gt;Learn a console text editor&lt;/h3&gt;&lt;p&gt;You will also want to get a decent grasp of a fully console-based text editor that is installed everywhere – Vi(m) or Nano. Nano is simpler, Vim is more powerful.&lt;/p&gt;&lt;p&gt;Just practice editing files with them for fun (write me an email in one!), and then you&amp;#39;ll know how to open files, navigate around, edit, save, and quit, when it matters. &lt;/p&gt;&lt;p&gt;Also: &lt;/p&gt;&lt;p&gt;System files generally need to be opened with &lt;code&gt;sudo&lt;/code&gt; (ie, &lt;code&gt;sudo vim path/to/file.conf&lt;/code&gt; or &lt;code&gt;sudoedit path/to/file.conf&lt;/code&gt;). If you don&amp;#39;t, you might make all your changes and then not be able to save!&lt;/p&gt;&lt;p&gt;If you&amp;#39;re in Vim when this happens, you can use &lt;code&gt;:w !sudo tee %&lt;/code&gt;. (In Helix, it’s &lt;code&gt;%:pipe-to sudo tee &amp;lt;Ctrl-r&amp;gt;%&lt;/code&gt;, but heed &lt;a href=&quot;https://github.com/helix-editor/helix/discussions/4251?ref=autodidacts.io#discussioncomment-17771897&quot;&gt;this warning&lt;/a&gt; about the importance of that first percentage sign to select all.)&lt;/p&gt;&lt;h3&gt;General advice&lt;/h3&gt;&lt;p&gt;Search the forums.&lt;/p&gt;&lt;p&gt;If necessary, post to the forums. Try to do your homework first. If people trying to help you are rude in their replies, try to ignore the tone and make use of the advice they give, be polite and grateful, and maybe do more homework next time.&lt;/p&gt;&lt;p&gt;The Arch Linux wiki is helpful even you don’t run Arch. Arch users have encountered nearly every bug under the sun. It tends to be pretty technical, though.&lt;/p&gt;&lt;p&gt;Reboot the machine.&lt;/p&gt;&lt;p&gt;Always backup first.&lt;/p&gt;&lt;p&gt;Try to understand commands before running them (but in practice sometimes you have to fly blind).&lt;/p&gt;&lt;p&gt;Unplug anything you don&amp;#39;t need plugged in.&lt;/p&gt;&lt;p&gt;Try to figure out what changed that might have triggered the problem.&lt;/p&gt;&lt;p&gt;Beware &amp;quot;Partial Upgrades&amp;quot;.&lt;/p&gt;&lt;p&gt;Do a fresh install from time to time.&lt;/p&gt;&lt;p&gt;Write down the exact time the problem occurred (so you can match it to log timestamps). Also, make sure to account for potential timezone differences: sometimes logs are in UTC.&lt;/p&gt;&lt;p&gt;Read my essay &lt;a href=&quot;https://www.autodidacts.io/troubleshooting/&quot;&gt;on troubleshooting&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Read the docs/manual for the software in question.&lt;/p&gt;&lt;p&gt;Keep trying.&lt;/p&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;p&gt;If this article helped you, share it with a friend. If it &lt;em&gt;didn’t &lt;/em&gt;help you, share it with an enemy. &amp;lt;3&lt;/p&gt;&lt;p&gt;If you know more than me, send me corrections and/or invective. If you know less than me, send me money and/or praise.&lt;/p&gt;&lt;p&gt;If you have an idea of how to fix the problem, try it. If you have no idea how to fix the problem, look it up. If the idea you had generated a &lt;em&gt;new&lt;/em&gt; error message, you are either getting closer or farther away from solving the problem. Google the new error message.&lt;/p&gt;&lt;p&gt;If nothing works, keep trying. If everything works, switch to BSD.&lt;/p&gt;&lt;p&gt;EOF&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Montray - a tray icon for systemd service health</title>
<link>https://github.com/dimonomid/montray/</link>
<guid isPermaLink="false">jR_xawaPQzYl1TIJCxPNxFdlLzajButoSkW__A==</guid>
<pubDate>Tue, 06 Oct 2026 16:33:05 +0000</pubDate>
<description>Comments</description>
<content:encoded>&lt;p&gt;&lt;a href=&quot;https://lobste.rs/s/gveu0c/montray_tray_icon_for_systemd_service&quot;&gt;Comments&lt;/a&gt;&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Por qué hoy uso Fedora · El blog de Lázaro</title>
<link>https://elblogdelazaro.org/por-que-hoy-uso-fedora/</link>
<enclosure type="image/jpeg" length="0" url="https://elblogdelazaro.org/images/og-default.png"></enclosure>
<guid isPermaLink="false">hiSjTsS03ZwABc3E7uam8z9k7rZmQyqWZzSbsw==</guid>
<pubDate>Tue, 06 Oct 2026 11:58:11 +0000</pubDate>
<description>Reflexión personal sobre por qué, tras años de distrohopping y ver morir muchas distros, he acabado quedándome en Fedora.</description>
<content:encoded>&lt;p&gt;Si llevas leyendo &lt;em&gt;&lt;strong&gt;El Blog de Lázaro&lt;/strong&gt;&lt;/em&gt; un tiempo, sabrás que llevo muchos años utilizando Linux como mi sistema principal. He vivido varias “&lt;em&gt;eras&lt;/em&gt;” distintas delante de la pantalla, y todavía recuerdo el boom de Ubuntu a mediados de los 2000, cuando Canonical te enviaba los CD de instalación completamente gratis a casa.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Era otra época: pedías el disco, esperabas unas semanas y, cuando llegaba el sobre, era casi como recibir un regalo de Reyes.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;picture&gt;&lt;img src=&quot;https://elblogdelazaro.org/images/posts/2026/fedora/fedora-02_hu_eaa4a6cf8f575d4f.png&quot; alt=&quot;CDs de Ubuntu del programa ShipIt&quot; title=&quot;&quot;/&gt;&lt;/picture&gt;&lt;/p&gt;&lt;p&gt;Aquello hizo que mucha gente, incluida la que no tenía ni idea de lo que era Linux, se atreviera a probarlo.&lt;/p&gt;&lt;h2&gt;Muerte de las pequeñas&lt;/h2&gt;&lt;p&gt;Con los años he visto nacer proyectos muy ilusionantes y también he visto desaparecer muchos. Es casi inevitable en un ecosistema tan vivo como el de Linux. A lo largo del tiempo se han ido desapareciendo nombres que en su momento sonaban fuerte: Mandrake, luego Mandriva, Antergos, Devuan, CrunchBang y unas cuantas más que hoy sólo sobreviven en capturas de pantalla y en la memoria de quienes las usaron.&lt;/p&gt;&lt;p&gt;Durante mucho tiempo esto no me importaba demasiado. Las distros iban y venían, y yo iba saltando de una a otra con la misma alegría con la que cambias de tema de fondo de pantalla.&lt;/p&gt;&lt;h2&gt;El espejismo de la popularidad&lt;/h2&gt;&lt;p&gt;Si miras hoy el top de DistroWatch, verás un montón de distribuciones muy populares, muchas de ellas sin una empresa grande detrás: CachyOS, EndeavourOS, MX Linux, Manjaro, Garuda, Linux Mint, Arch Linux, todas muy queridas por la comunidad y con un empuje impresionante. A excepción de Debian, que sí tiene una historia y una estructura muy particular, la mayoría se apoyan sobre todo en el trabajo voluntario de desarrolladores y colaboradores.&lt;/p&gt;&lt;p&gt;Eso está genial mientras el proyecto está vivo y la comunidad tiene fuerzas. El problema es qué pasa dentro de cinco o diez años.&lt;/p&gt;&lt;h2&gt;Las grandes que siempre resisten&lt;/h2&gt;&lt;p&gt;Con el tiempo he ido viendo un patrón muy claro: las distribuciones que aguantan el paso de los años suelen ser las grandes. Ahí están SUSE, Fedora y, por supuesto, la madre de todas las distros, Debian, que lleva décadas sirviendo de base a medio ecosistema Linux.&lt;/p&gt;&lt;p&gt;Todas ellas tienen algo en común: detrás hay estructuras organizadas y empresas serias. Eso no las hace perfectas, pero sí les da una continuidad que empiezas a valorar mucho más que a la novedad.&lt;/p&gt;&lt;h2&gt;La búsqueda de la estabilidad&lt;/h2&gt;&lt;p&gt;Cuando era más joven, no me importaba ir saltando entre distros. Me encantaba ese momento de instalar desde cero, pelearme con algún driver, afinar la configuración y dejar todo “niquelado”. Si algo se rompía después de una actualización, me lo tomaba casi como un reto personal.&lt;/p&gt;&lt;p&gt;Hoy no. Hoy enciendo el ordenador y quiero que arranque, que mi entorno esté tal y como lo dejé ayer y que no tenga que perder la tarde solucionando problemas. Ahora prefiero dedicarla a trabajar, escribir, aprender o simplemente disfrutar.&lt;/p&gt;&lt;h2&gt;Por qué elijo Fedora&lt;/h2&gt;&lt;p&gt;En ese cambio de prioridades es donde entra Fedora. Lo que me da Fedora es precisamente esa combinación: un sistema moderno, con software relativamente reciente, pero con una base muy sólida, bien pensada y respaldada por una comunidad enorme y por Red Hat detrás. No necesito que sea la distro más top de DistroWatch; necesito que sea la que menos ruido hace en mi día a día.&lt;/p&gt;&lt;p&gt;&lt;picture&gt;&lt;img src=&quot;https://elblogdelazaro.org/images/posts/2026/fedora/fedora-01_hu_7b001da7b22335a8.png&quot; alt=&quot;Logo de Fedora sobre fondo azul&quot; title=&quot;&quot;/&gt;&lt;/picture&gt;&lt;/p&gt;&lt;p&gt;Ya no me apetece andar reinstalando cada dos por tres ni persiguiendo pequeñas errores después de cada actualización importante. Con Fedora siento que puedo actualizar con bastante tranquilidad y seguir con mi vida. No es perfecta (ninguna lo es), pero se ha ganado mi confianza.&lt;/p&gt;&lt;h2&gt;Lo que hace realmente grande a Linux&lt;/h2&gt;&lt;p&gt;Y, a pesar de todo esto, hay algo que quiero dejar claro: que yo haya elegido Fedora no significa que sea “la distro correcta” ni que el resto no merezcan la pena. En realidad, lo que hace a Linux tan interesante y tan grande es precisamente su variedad de opciones. Hay distribuciones minimalistas, otras para principiantes, algunas casi experimentales, otras pensadas sólo para servidore y otas ultra ligeras para equipos antiguos.&lt;/p&gt;&lt;p&gt;No todos queremos lo mismo, ni trabajamos igual, ni tenemos las mismas prioridades. Hay quien disfruta probando una distro nueva cada mes y hay quien prefiere instalar una vez y olvidarse durante años. Hay quien valora la novedad por encima de todo y quien, como me pasa a mí ahora, valora por encima de todo la estabilidad y la tranquilidad.&lt;/p&gt;&lt;h2&gt;Mi elección&lt;/h2&gt;&lt;p&gt;Al final, al igual que nosotros cambiamos con el tiempo, también lo hacen nuestras necesidades y siempre habrá una distribución que encaje con la etapa en la que estamos. En mi caso, hoy esa pieza se llama Fedora. Mañana, ya veremos.&lt;/p&gt;&lt;p&gt;Espero que te haya gustado, pasa un buen día. 🐧&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Forgot Your Root Password? Here&amp;#8217;s the Easy Way (and the Hard Way) to Recover It</title>
<link>https://lowendbox.com/blog/forgot-your-root-password-heres-the-easy-way-and-the-hard-way-to-recover-it/</link>
<guid isPermaLink="false">TKyW-tSTiGZr3tmzRBi6EAN0JEMngykQdyx-kw==</guid>
<pubDate>Tue, 06 Oct 2026 11:45:38 +0000</pubDate>
<description>Forgot your root password? It happens. We&#39;re not judging. We&#39;ll help you get it back, either through the SolusVM panel or at the command line with a rescue image if you need it. The post Forgot Your Root Password? Here’s the Easy Way (and the Hard Way) to Recover It appeared first on LowEndBox.</description>
<content:encoded>&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/lost-root-password-300x300.png&quot; alt=&quot;Lost Root Password&quot; title=&quot;&quot;/&gt;It happens.  No judging here.  You created a 32-character password chock full of special character goodness and you &lt;em&gt;thought&lt;/em&gt; you’d made a note in your password manager but somehow, you didn’t.  You didn’t setup &lt;code&gt;sudo&lt;/code&gt; or &lt;code&gt;doas&lt;/code&gt;, and now you need to do something as root and you can’t.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Oh no!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;But not all is lost.  There’s at least two ways to fix the issue.&lt;/p&gt;&lt;h2&gt;Using Your Panel&lt;/h2&gt;&lt;p&gt;The first thing to check is if the provider’s panel supports root password resets.  It’s almost like hosting companies get so many requests to reset root passwords that the hosting panel providers built it in to save them headaches…hmmm.&lt;/p&gt;&lt;p&gt;I logged into Solus on &lt;a href=&quot;https://racknerd.com/&quot;&gt;RackNerd&lt;/a&gt; and here is what I see:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solus-root-password-reset-1024x601.png&quot; alt=&quot;Solus Root Password Reset&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;So let’s try that.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solus-root-password-reset-2-1024x173.png&quot; alt=&quot;Solus Root Password Reset&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;After clicking change, you get this message:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solus-root-password-reset-3-1024x519.png&quot; alt=&quot;Solus Root Password Reset&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;And then after clicking Yes:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solus-root-password-reset-4-1024x358.png&quot; alt=&quot;Solus Root Password Reset&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;(Don’t worry – I’ll change it before this article is published!)&lt;/p&gt;&lt;p&gt;After a little processing, it’s successful:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solus-root-password-reset-5-1024x360.png&quot; alt=&quot;Solus Root Password Reset&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Now in my case, there was only one problem.  As part of my VPS setup, my Ansible scripts put this in &lt;code&gt;/etc/ssh/sshd_config&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;PermitRootLogin without-password&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;So it actually was not possible for me to login as root.  In this particular case, losing the root password didn’t actually matter because I could login with my ssh key, but you get the point.  If I’d lost the ssh key, I’d have been hosed.&lt;/p&gt;&lt;h2&gt;Using Rescue&lt;/h2&gt;&lt;p&gt;Let’s look at the SolusVM rescue mode:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solusvm-rescue-1024x247.png&quot; alt=&quot;SolusVM Rescue&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Clicking that gives a warning:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solusvm-rescue-2-1024x270.png&quot; alt=&quot;SolusVM Rescue&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;I clicked “Enable Rescue Mode” and SolusVM politely asked me to confirm:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solusvm-rescue-3-1024x305.png&quot; alt=&quot;SolusVM Rescue&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;Yes, please.&lt;/p&gt;&lt;p&gt;After clicking Yes:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://lowendbox.com/wp-content/uploads/2026/09/solusvm-rescue4a-1024x363.png&quot; alt=&quot;SolusVM Rescue&quot; title=&quot;&quot;/&gt;&lt;/p&gt;&lt;p&gt;I let it boot a bit, and then was able to login from my PC:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;$ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@&amp;lt;my IP&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Whoa…what’s up with all those -o flags?  If you don’t use them, you’ll get the dramatic warning that “IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!”&lt;/p&gt;&lt;p&gt;The reason is that the IP is in my hosts file as associated with a certain host key, and when I boot in rescue mode, its’s a completely different OS image.  So my ssh client gets a totally different host key and throws the flag.  The -o flags I listed ignore that temporarily, without having to go in and modify the &lt;code&gt;known_hosts&lt;/code&gt; file.&lt;/p&gt;&lt;p&gt;Now after logging in, it’s important to note that &lt;strong&gt;I am not logged into my VPS per se&lt;/strong&gt;.  I’m logged into a rescue image.  For example:&lt;/p&gt;&lt;pre&gt;rescue # cat /etc/hostname
rescue
&lt;/pre&gt;&lt;p&gt;If I was to run &lt;code&gt;passwd root&lt;/code&gt; now, I’d be changing the rescue image password, which is pointless.&lt;/p&gt;&lt;p&gt;So we have a little work to do.  First, find the actual root partition of your VPS:&lt;/p&gt;&lt;pre&gt;rescue # mount | grep &amp;quot;on / &amp;quot;
/dev/vdb1 on / type ext3 (rw,relatime,discard,errors=remount-ro,data=ordered)
rescue # lsblk -f
NAME   FSTYPE LABEL UUID                                 MOUNTPOINT
sr0                                                      
vda                                                      
├─vda1 ext4         a09aaadc-93fd-4c32-af29-f007d7c429f6 
└─vda2 swap         ab346e4e-071f-491e-a512-2dcabaff20bd 
vdb                                                      
└─vdb1 ext3         0e8b889c-8efb-4093-9d42-817ae3ca1f90 /
rescue # 
&lt;/pre&gt;&lt;p&gt;OK, so the rescue environment is &lt;code&gt;/dev/vdb1&lt;/code&gt;.  &lt;code&gt;/dev/vda1&lt;/code&gt; is my actual root.  So let’s prep a chroot environment for that.&lt;/p&gt;&lt;pre&gt;rescue # mount /dev/vda1 /mnt
rescue # mount --bind /dev  /mnt/dev
rescue # mount --bind /proc /mnt/proc
rescue # mount --bind /sys  /mnt/sys
rescue # mount --bind /run  /mnt/run
&lt;/pre&gt;&lt;p&gt;And then enter the chroot environment:&lt;/p&gt;&lt;pre&gt;rescue # chroot /mnt /bin/bash
&lt;/pre&gt;&lt;p&gt;Now I am in my actual VPS. For example:&lt;/p&gt;&lt;pre&gt;root@rescue:/# cat /etc/hostname
vpn-chi-1
root@rescue:/# 
&lt;/pre&gt;&lt;p&gt;And now I can reset the root password:&lt;/p&gt;&lt;pre&gt;root@rescue:/# passwd
New password: 
Retype new password: 
passwd: password updated successfully
root@rescue:/# exit
exit
rescue # reboot
&lt;/pre&gt;&lt;p&gt;The post &lt;a href=&quot;https://lowendbox.com/blog/forgot-your-root-password-heres-the-easy-way-and-the-hard-way-to-recover-it/&quot;&gt;Forgot Your Root Password? Here’s the Easy Way (and the Hard Way) to Recover It&lt;/a&gt; appeared first on &lt;a href=&quot;https://lowendbox.com&quot;&gt;LowEndBox&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>Taming GCE Memory Tax: Disabling OS Login and OS Config on Small Instances // Tony Metzidis</title>
<link>https://tonym.us/taming-gce-memory-tax-oslogin-osconfig.html</link>
<guid isPermaLink="false">03k4-gOVbR1gLS8sClvZQPFScVsA_01BDBOckA==</guid>
<pubDate>Tue, 06 Oct 2026 11:34:46 +0000</pubDate>
<description>Google Compute Engine’s e2-micro instances are a staple of the GCP Free Tier, offering 2 vCPUs and roughly 1 GB of RAM (969 MiB usable). They are ideal for lightweight bastions, cron runners, and small test beds. However, if you run memory-sensitive workloads—such as Go builds, package extractions, or continuous process forks—you may have experienced intermittent, baffling SSH connection timeouts and unresponsive terminals. The root cause is rarely your application alone. By default, GC...</description>
<content:encoded>&lt;p&gt;Google Compute Engine’s &lt;code&gt;e2-micro&lt;/code&gt; instances are a staple of the GCP Free Tier, offering 2 vCPUs and roughly 1 GB of RAM (969 MiB usable). They are ideal for lightweight bastions, cron runners, and small test beds. However, if you run memory-sensitive workloads—such as Go builds, package extractions, or continuous process forks—you may have experienced intermittent, baffling SSH connection timeouts and unresponsive terminals.&lt;/p&gt;&lt;p&gt;The root cause is rarely your application alone. By default, GCE provisions a suite of Google guest daemons that consume a disproportionate share of resident memory on small VMs, creating an environment primed for SSH exhaustion.&lt;/p&gt;&lt;hr/&gt;&lt;h3&gt;The Anatomy of the 15% Memory Tax&lt;/h3&gt;&lt;p&gt;Running a bare Debian 12 Bookworm instance on an &lt;code&gt;e2-micro&lt;/code&gt; without any user workload active reveals an astonishing baseline:&lt;/p&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Process / Daemon&lt;/th&gt;
          &lt;th&gt;Command Name&lt;/th&gt;
          &lt;th&gt;Resident RAM (RSS)&lt;/th&gt;
          &lt;th&gt;% of 1 GB RAM&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Google OS Config Agent&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;google_osconfig&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~61.8 MB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~6.2%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Guest Agent Core Plugin&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;core_plugin&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~27.7 MB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~2.8%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Guest Agent Manager&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;google_guest_ag&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~27.2 MB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~2.7%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Guest Compat Manager&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;google_guest_co&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~19.7 MB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~2.0%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Guest Telemetry Extension&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;guest_telemetry&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~18.7 MB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~1.9%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Total Google Guest Footprint&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~155.1 MB&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~15.6%&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;p&gt;On a 16 GB node, a 155 MB footprint is negligible noise (&amp;lt; 1%). On a 1 GB instance without swap space, &lt;strong&gt;15.6% of your physical memory is permanently claimed before your application even boots&lt;/strong&gt;.&lt;/p&gt;&lt;hr/&gt;&lt;h3&gt;Why OS Config Hoards 62 MB of RAM&lt;/h3&gt;&lt;p&gt;Static analysis of the &lt;a href=&quot;https://github.com/GoogleCloudPlatform/osconfig&quot;&gt;&lt;code&gt;GoogleCloudPlatform/osconfig&lt;/code&gt;&lt;/a&gt; repository reveals why &lt;code&gt;google_osconfig&lt;/code&gt; claims over 60 MB alone:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Embedded Vulnerability Scanners&lt;/strong&gt;: Rather than calling out to an external CLI tool and exiting, &lt;code&gt;osconfig&lt;/code&gt; embeds Google’s &lt;code&gt;osv-scalibr&lt;/code&gt; scanner directly in-process. It parses package databases (&lt;code&gt;dpkg&lt;/code&gt;, &lt;code&gt;rpm&lt;/code&gt;, &lt;code&gt;pip&lt;/code&gt;, &lt;code&gt;gem&lt;/code&gt;) into memory trees.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heavy Protobuf &amp;amp; gRPC Slices&lt;/strong&gt;: Every inventory cycle instantiates fresh gRPC client transports and serializes thousands of package messages into contiguous memory chunks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go Runtime Retention&lt;/strong&gt;: The Go garbage collector runs, but memory marked as free (&lt;code&gt;madvise(MADV_DONTNEED)&lt;/code&gt;) is not eagerly returned to the kernel RSS table. It holds its high-water mark indefinitely.&lt;/li&gt;
&lt;/ol&gt;&lt;hr/&gt;&lt;h3&gt;The SSH Starvation Cascade: How OS Login Fails Under Load&lt;/h3&gt;&lt;p&gt;When your application executes builds or unpacks files, kernel VFS slab caches (&lt;code&gt;dentry&lt;/code&gt;, &lt;code&gt;ext4_inode_cache&lt;/code&gt;) grow dynamically. When total physical RAM nears exhaustion, Linux enters severe memory pressure (surfacing in &lt;code&gt;/proc/pressure/memory&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;If &lt;strong&gt;OS Login&lt;/strong&gt; (&lt;code&gt;enable-oslogin=TRUE&lt;/code&gt;) is active, incoming SSH connections must complete the following chain:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;sshd&lt;/code&gt; receives a TCP connection on port 22.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sshd&lt;/code&gt; executes &lt;code&gt;AuthorizedKeysCommand&lt;/code&gt; (&lt;code&gt;/usr/bin/google_authorized_keys&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The PAM stack loads &lt;code&gt;/lib/security/pam_oslogin_login.so&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;PAM performs IPC calls or local HTTP round-trips to the GCE metadata server (&lt;code&gt;169.254.169.254&lt;/code&gt;) to verify IAM permissions and POSIX mappings.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Under memory stall conditions (PSI &lt;code&gt;some avg10 &amp;gt; 2.0&lt;/code&gt;), &lt;code&gt;fork()&lt;/code&gt; calls stall, metadata socket round-trips lag, and the SSH client hits its default &lt;code&gt;ConnectTimeout&lt;/code&gt; (5–10s). The user sees:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;ssh: connect to host 34.xx.xx.xx port 22: Connection timed out
# or
Connection reset by peer / Permission denied (publickey)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Conversely, with standard SSH authorized keys, &lt;code&gt;sshd&lt;/code&gt; opens local &lt;code&gt;/home/&amp;lt;user&amp;gt;/.ssh/authorized_keys&lt;/code&gt; directly with a single disk read, bypassing external IPC entirely.&lt;/p&gt;&lt;hr/&gt;&lt;h3&gt;Reclaiming Your RAM: Disabling OS Config &amp;amp; OS Login&lt;/h3&gt;&lt;p&gt;If you don’t use GCP VM Manager (automated patch management dashboards in the Cloud Console) or IAM-based OS Login, disabling them recovers immediate memory and makes SSH bulletproof.&lt;/p&gt;&lt;h4&gt;Option 1: Project-Level Metadata (Recommended)&lt;/h4&gt;&lt;p&gt;You can enforce this across all instances in a project with two &lt;code&gt;gcloud&lt;/code&gt; commands:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 1. Disable OS Config and OS Login project-wide
gcloud compute project-info add-metadata \
    --project=&amp;quot;my-project&amp;quot; \
    --metadata=enable-osconfig=FALSE,enable-oslogin=FALSE

# 2. Add your static SSH public key to project metadata
gcloud compute project-info add-metadata \
    --project=&amp;quot;my-project&amp;quot; \
    --metadata=&amp;quot;ssh-keys=tonymet:$(cat ~/.ssh/id_rsa.pub)&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Note: Disabling OS Login allows the standard &lt;code&gt;google-guest-agent&lt;/code&gt; to automatically read the project-wide &lt;code&gt;ssh-keys&lt;/code&gt; metadata and write &lt;code&gt;/home/tonymet/.ssh/authorized_keys&lt;/code&gt; on every instance.&lt;/em&gt;&lt;/p&gt;&lt;h4&gt;Option 2: Inside the Operating System&lt;/h4&gt;&lt;p&gt;If you prefer to disable the services directly inside the VM:&lt;/p&gt;&lt;div&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Stop and mask the OS Config service
sudo systemctl stop google-osconfig-agent
sudo systemctl disable --now google-osconfig-agent
sudo systemctl mask google-osconfig-agent

# Optional: Completely remove the package
sudo apt-get purge -y google-osconfig-agent&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr/&gt;&lt;h3&gt;Telemetry Comparison: Before vs. After&lt;/h3&gt;&lt;p&gt;Using our synthetic stress harness on an &lt;code&gt;e2-micro&lt;/code&gt; running Debian 12 (pinned 250 MB heap anchor, 10,000 file/dentry cycles, and continuous process execution churn):&lt;/p&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Metric&lt;/th&gt;
          &lt;th&gt;Agents Active (Control)&lt;/th&gt;
          &lt;th&gt;Agents Stopped (Treatment)&lt;/th&gt;
          &lt;th&gt;Improvement&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Baseline Resident RAM&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;~325 MB used&lt;/td&gt;
          &lt;td&gt;~170 MB used&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;~155 MB recovered&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Max Memory Stall (&lt;code&gt;some avg10&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;2.37&lt;/td&gt;
          &lt;td&gt;0.62&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-73.8% pressure stall reduction&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Max Full Memory Stall (&lt;code&gt;full avg10&lt;/code&gt;)&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;1.74&lt;/td&gt;
          &lt;td&gt;0.38&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;-78.2% full stall reduction&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;SSH Probe Failure Rate&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;0 timeouts&lt;/td&gt;
          &lt;td&gt;0 timeouts&lt;/td&gt;
          &lt;td&gt;Sub-second latency&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;hr/&gt;&lt;h3&gt;Key Takeaways&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Know Your Guest Footprint&lt;/strong&gt;: Google guest agents provide cloud-native conveniences, but their ~155 MB overhead is disproportionately taxing on free-tier 1 GB instances.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OS Config is Optional&lt;/strong&gt;: Disabling it only removes centralized fleet patching and inventory dashboards from the Cloud Console; basic VM operations, networking, and standard updates remain 100% intact.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simpler Auth is Resilient Auth&lt;/strong&gt;: On constrained systems, local authorized keys eliminate IPC round-trips to the metadata server, ensuring reliable console access even when the system is under stress.&lt;/li&gt;
&lt;/ol&gt;</content:encoded>
</item>
<item>
<title>Installing CuBox-i firmware on Debian Linux (CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro)</title>
<link>https://www.jamescherti.com/installing-firmware-debian-linux-cubox-i1-i2-i2ex-i4pro/</link>
<guid isPermaLink="false">YadqsbsTbOVE1C02hZzx80GuLEN7TckYJhB_AQ==</guid>
<pubDate>Tue, 06 Oct 2026 10:01:55 +0000</pubDate>
<description>After installing Debian Linux on the CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro, additional firmware files are required for Wi-Fi, SDMA, and hardware-accelerated video decoding. Specifically, the VPU needs proprietary firmware, the Wi-Fi module relies on symlinking files from an official Debian package, and the SDMA engine depends on the non-free firmware package. For context, the following dmesg output from a CuBox-i4Pro demonstrates the missing firmware warnings: This article explains h...</description>
<content:encoded>&lt;p&gt;After &lt;a href=&quot;https://www.jamescherti.com/install-debian-cubox-i/&quot;&gt;&lt;strong&gt;installing Debian Linux on the CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro&lt;/strong&gt;&lt;/a&gt;, additional firmware files are required for Wi-Fi, SDMA, and hardware-accelerated video decoding. Specifically, the VPU needs proprietary firmware, the Wi-Fi module relies on symlinking files from an official Debian package, and the SDMA engine depends on the non-free firmware package. For context, the following &lt;code&gt;dmesg&lt;/code&gt; output from a CuBox-i4Pro demonstrates the missing firmware warnings:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;coda 2040000.vpu: firmware: failed to load vpu_fw_imx6q.bin (-2)
coda 2040000.vpu: Direct firmware load for vpu_fw_imx6q.bin failed with error -2
coda 2040000.vpu: firmware: failed to load vpu/vpu_fw_imx6q.bin (-2)
coda 2040000.vpu: Direct firmware load for vpu/vpu_fw_imx6q.bin failed with error -2

coda 2040000.vpu: firmware: failed to load v4l-coda960-imx6q.bin (-2)
coda 2040000.vpu: Direct firmware load for v4l-coda960-imx6q.bin failed with error -2

brcmfmac mmc0:0001:1: firmware: failed to load brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.bin (-2)
brcmfmac mmc0:0001:1: firmware: failed to load brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.bin (-2)
brcmfmac mmc0:0001:1: firmware: failed to load brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.bin (-2)
brcmfmac mmc0:0001:1: Direct firmware load for brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.bin failed with error -2&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;This article explains how to install the missing firmware.&lt;/p&gt;&lt;h1&gt;Firmware 1: The integrated Video Processing Unit (VPU)&lt;/h1&gt;&lt;p&gt;The CuBox-i computers includes an integrated Video Processing Unit (VPU) for hardware-accelerated video encoding and decoding. The Debian non-free repositories do not package the proprietary Video Processing Unit firmware files. You can download the files directly from the Armbian firmware repository.&lt;/p&gt;&lt;h3&gt;For the CuBox-i2eX or CuBox-i4Pro VPU&lt;/h3&gt;&lt;p&gt;Run the following command as root to download the Video Processing Unit firmware for the CuBox-i2eX or CuBox-i4Pro:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;wget -O /lib/firmware/vpu_fw_imx6q.bin https://github.com/armbian/firmware/raw/refs/heads/master/vpu/vpu_fw_imx6q.bin
wget -O /lib/firmware/v4l-coda960-imx6q.bin https://github.com/armbian/firmware/raw/refs/heads/master/v4l-coda960-imx6q.bin&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h3&gt;For the CuBox-i1 or CuBox-i2 VPU&lt;/h3&gt;&lt;p&gt;Run the following command as root to download the Video Processing Unit firmware for the CuBox-i1 or CuBox-i2:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;wget -O /lib/firmware/v4l-coda960-imx6dl.bin https://github.com/armbian/firmware/raw/refs/heads/master/v4l-coda960-imx6dl.bin
wget -O /lib/firmware/vpu_fw_imx6d.bin https://github.com/armbian/firmware/raw/refs/heads/master/imx/vpu/vpu_fw_imx6d.bin&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Firmware 2: SDMA&lt;/h2&gt;&lt;p&gt;The mainline i.MX6 device tree specifies &lt;em&gt;imx/sdma/sdma-imx6q.bin&lt;/em&gt; for the SDMA engine (Smart Direct Memory Access). If the external firmware is unavailable, the Linux driver can fall back to firmware embedded in the SoC ROM. The external firmware provides additional and updated SDMA scripts for peripherals that use SDMA.&lt;/p&gt;&lt;p&gt;To provide the required firmware files, install the &lt;code&gt;firmware-misc-nonfree&lt;/code&gt; package:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;apt-get install firmware-misc-nonfree&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Once the package is installed, update the initramfs to ensure the binaries are included in the boot image:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;update-initramfs -u -k all&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Firmware 3: Broadcom Wi-Fi firmware&lt;/h2&gt;&lt;h3&gt;Step 1: Install the Broadcom Wi-Fi firmware package&lt;/h3&gt;&lt;p&gt;Install the &lt;em&gt;firmware-brcm80211&lt;/em&gt; package:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;apt-get install firmware-brcm80211&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;The firmware-&lt;em&gt;brcm80211&lt;/em&gt; package provides the generic firmware file. The Linux driver can additionally request a board-specific firmware and NVRAM file based on the device tree.&lt;/p&gt;&lt;h3&gt;Step 2: Configure the missing Broadcom Wi-Fi firmware files&lt;/h3&gt;&lt;p&gt;Run the following commands as root to symlink the installed firmware and fallback configuration to the board-specific filenames:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;ln -s /lib/firmware/brcm/brcmfmac4330-sdio.bin /lib/firmware/brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.bin
ln -s /lib/firmware/brcm/brcmfmac4329-sdio.bin /lib/firmware/brcm/brcmfmac4329-sdio.solidrun,cubox-i-q.bin
ln -s /lib/firmware/brcm/brcmfmac4330-sdio.bin /lib/firmware/brcm/brcmfmac4330-sdio.solidrun,cubox-i-dl.bin
ln -s /lib/firmware/brcm/brcmfmac4329-sdio.bin /lib/firmware/brcm/brcmfmac4329-sdio.solidrun,cubox-i-dl.bin&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h3&gt;Step 3: Download the CuBox-i Broadcom NVRAM configuration&lt;/h3&gt;&lt;p&gt;The Linux &lt;em&gt;brcmfmac&lt;/em&gt; driver expects a board-specific NVRAM file. Download the configuration provided by SolidRun and install it under &lt;code&gt;/lib/firmware/brcm/&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;wget -O /lib/firmware/brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.txt https://raw.githubusercontent.com/SolidRun/meta-solidrun-arm-imx6/jethro/recipes-bsp/broadcom-nvram-config/files/solidrun-imx6/brcmfmac4330-sdio.txt
wget -O /lib/firmware/brcm/brcmfmac4329-sdio.solidrun,cubox-i-q.txt https://raw.githubusercontent.com/SolidRun/meta-solidrun-arm-imx6/jethro/recipes-bsp/broadcom-nvram-config/files/solidrun-imx6/brcmfmac4329-sdio.txt
wget -O /lib/firmware/brcm/brcmfmac4330-sdio.solidrun,cubox-i-dl.txt https://raw.githubusercontent.com/SolidRun/meta-solidrun-arm-imx6/jethro/recipes-bsp/broadcom-nvram-config/files/solidrun-imx6/brcmfmac4330-sdio.txt
wget -O /lib/firmware/brcm/brcmfmac4329-sdio.solidrun,cubox-i-dl.txt https://raw.githubusercontent.com/SolidRun/meta-solidrun-arm-imx6/jethro/recipes-bsp/broadcom-nvram-config/files/solidrun-imx6/brcmfmac4329-sdio.txt&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h3&gt;Step 4: The WiFi regulatory domain&lt;/h3&gt;&lt;p&gt;The NVRAM file needs to have the correct WiFi regulatory domain set. This can be done by setting the value of the &lt;em&gt;ccode&lt;/em&gt; parameter to the country code in which the device will be operating in. For example, to set the WiFi regulatory domain for the United States:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;sed -i &amp;#39;s/^ccode=.*/ccode=US/&amp;#39; /lib/firmware/brcm/brcmfmac4330-sdio.solidrun,cubox-i-q.txt
sed -i &amp;#39;s/^ccode=.*/ccode=US/&amp;#39; /lib/firmware/brcm/brcmfmac4329-sdio.solidrun,cubox-i-q.txt
sed -i &amp;#39;s/^ccode=.*/ccode=US/&amp;#39; /lib/firmware/brcm/brcmfmac4330-sdio.solidrun,cubox-i-dl.txt
sed -i &amp;#39;s/^ccode=.*/ccode=US/&amp;#39; /lib/firmware/brcm/brcmfmac4329-sdio.solidrun,cubox-i-dl.txt&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Note: Replace &amp;#39;US&amp;#39; with &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/tree/db.txt&quot;&gt;your country code&lt;/a&gt;.&lt;/p&gt;&lt;h2&gt;Reboot&lt;/h2&gt;&lt;p&gt;Rebooting the system will allow the drivers to load the firmware files and clear the initialization failures.&lt;/p&gt;&lt;h2&gt;Similar articles&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/install-debian-cubox-i/&quot;&gt;&lt;strong&gt;Installing Debian Linux on the CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;h3&gt;Related posts:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/secure-fail2ban-ssh-linux/&quot;&gt;Protecting SSH with Fail2ban on Linux systems, such as Debian, Ubuntu, Arch Linux, Linux Mint, Debian, Kali Linux, raspbian, Gentoo, etc.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ergonomic-workstation/&quot;&gt;My Ergonomic Workstation: Enhancing Focus, Comfort, and Efficiency&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/install-debian-cubox-i/&quot;&gt;Installing Debian on a CuBox-i computer (CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/&quot;&gt;Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-arch-linux-from-debian-system-ubuntu-linux-mint/&quot;&gt;Installing Arch Linux onto a separate partition from an existing Debian-based distribution (Ubuntu, Debian, Linux Mint...), without using the Arch Linux installation media&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/emacs-dir-locals-add-path-to-pythonpath/&quot;&gt;Emacs .dir-locals.el - Add project path to $PYTHONPATH (Python Development in Emacs)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/the-jc-dotfiles-repository/&quot;&gt;jc-dotfiles - James Cherti&amp;#39;s Dotfiles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/my-software-dev-journey-from-dos-and-windows-95-to-linux/&quot;&gt;How breaking Windows 30 years ago turned me into a software developer and Linux professional&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-install-gitolite-linux/&quot;&gt;ansible-role-gitolite - An Ansible role that automates the installation and configuration of Gitolite, a Git repository management system&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gnome-shell-extensions-to-install-from-apt-debian-repositories/&quot;&gt;13 Useful GNOME Shell Extensions for a Better Desktop Experience (Available in the official Debian repositories or on the GNOME Extensions website for other distributions)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/bios-setting-performance-lenovo-thinkpad-t-w-x-series/&quot;&gt;BIOS settings for performance on older ThinkPads, such as T420, T420s, T520, W520, X220, T430...&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/script-update-arch-linux/&quot;&gt;Helper script to upgrade Arch Linux&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/make-vim-edit-or-diff-files-from-outside-vim-from-shell-bash-zsh/&quot;&gt;vim-client - send commands to the Vim editor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-role-reniced/&quot;&gt;ansible-role-reniced - An Ansible role that configures reniced&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/change-default-gdm-login-monitor-gnome-multi-monitor/&quot;&gt;Linux: Setting the default GDM login monitor in a multi-monitor setup using GNOME display settings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/tmux-autocomplete-fzf-fuzzy-insertion-scrollback/&quot;&gt;Bash shell: Interactive Menu to Insert any String from the Tmux Scrollback Buffer Into the Shell Prompt&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/pathaction/&quot;&gt;Pathaction | A universal Makefile for any file in the filesystem: Rule-driven commands for any file or directory&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-role-auto-upgrade-an-ansible-role-that-automates-upgrading-linux-operating-systems/&quot;&gt;ansible-role-auto-upgrade - Ansible role for automated upgrades of Linux systems&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/wordpress-disable-xml-rpc/&quot;&gt;Disabling XML-RPC in WordPress for Security and Performance&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded>
</item>
<item>
<title>BIOS settings for performance on older ThinkPads, such as T420, T420s, T520, W520, X220, T430...</title>
<link>https://www.jamescherti.com/bios-setting-performance-lenovo-thinkpad-t-w-x-series/</link>
<guid isPermaLink="false">lOU1wJ67PXThv0kBusgR46nQPxew7CRgYA-yMQ==</guid>
<pubDate>Tue, 06 Oct 2026 10:01:55 +0000</pubDate>
<description>Older Lenovo ThinkPad models such as the T420, T420s, T520, X220, W520, and T430 provide BIOS settings that control CPU power management, processor features, storage controllers, and boot behavior. Adjusting some of these settings can improve responsiveness or reduce boot time. CPU and Power Delivery CPU Power Management Disabling CPU Power Management turns off the BIOS feature that stops the processor clock during periods of inactivity. The benefit is that the operating system gains unrestri...</description>
<content:encoded>&lt;p&gt;Older Lenovo ThinkPad models such as the T420, T420s, T520, X220, W520, and T430 provide BIOS settings that control CPU power management, processor features, storage controllers, and boot behavior. Adjusting some of these settings can improve responsiveness or reduce boot time.&lt;/p&gt;&lt;h2&gt;CPU and Power Delivery&lt;/h2&gt;&lt;h3&gt;CPU Power Management&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Path: Config -&amp;gt; Power -&amp;gt; CPU Power Management&lt;/li&gt;&lt;li&gt;Setting: Disabled.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Disabling CPU Power Management turns off the BIOS feature that stops the processor clock during periods of inactivity. The benefit is that the operating system gains unrestricted control over processor state transitions, reducing latency.&lt;/p&gt;&lt;p&gt;The tradeoff is higher baseline power consumption when the system is idle. Ensure your operating system is configured with an appropriate CPU frequency scaling governor, otherwise the processor will constantly run at its maximum clock speed.&lt;/p&gt;&lt;h3&gt;Intel SpeedStep Technology&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Path: Config -&amp;gt; Power -&amp;gt; Intel SpeedStep Technology&lt;/li&gt;&lt;li&gt;Setting: Set Mode for AC and Mode for Battery to Maximum Performance.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Setting both AC and battery operation to Maximum Performance selects the highest-performance SpeedStep mode rather than the battery-optimized mode. (Note: This can increase CPU power consumption and battery usage.)&lt;/p&gt;&lt;h2&gt;CPU Core Utilization&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Path: Config -&amp;gt; CPU&lt;/li&gt;&lt;li&gt;Settings: Ensure both Core Multi-Processing and Intel Hyper-Threading Technology are Enabled.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These settings allow the operating system to use all available physical cores and logical processors.&lt;/p&gt;&lt;h2&gt;Boot Time Reduction&lt;/h2&gt;&lt;h3&gt;Boot order&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Path: Startup -&amp;gt; Boot&lt;/li&gt;&lt;li&gt;Setting: Move the primary OS drive (SSD/HDD) to the top of the boot priority list.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Placing the primary OS drive near the top of the boot order can reduce delays caused by firmware attempting earlier boot targets before reaching the operating system drive. The tradeoff is requiring manual intervention via the boot menu to boot from external media.&lt;/p&gt;&lt;h3&gt;Boot mode&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;Path: Startup -&amp;gt; Boot Mode&lt;/li&gt;&lt;li&gt;Setting: Quick.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The benefit is a reduction in total system startup time, accelerating the transition from the Lenovo splash screen to the OS bootloader.&lt;/p&gt;&lt;h2&gt;Storage Controller Optimization&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Path: Config -&amp;gt; Serial ATA (SATA)&lt;/li&gt;&lt;li&gt;Setting: Change Controller Mode Option to AHCI.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;AHCI is generally the appropriate SATA controller mode for modern Linux and Windows installations. (Note: Older operating systems must have AHCI drivers.)&lt;/p&gt;&lt;h2&gt;Similar articles&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/&quot;&gt;Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;h3&gt;Related posts:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/install-debian-cubox-i/&quot;&gt;Installing Debian on a CuBox-i computer (CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/the-jc-dotfiles-repository/&quot;&gt;jc-dotfiles - James Cherti&amp;#39;s Dotfiles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/my-software-dev-journey-from-dos-and-windows-95-to-linux/&quot;&gt;How breaking Windows 30 years ago turned me into a software developer and Linux professional&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/&quot;&gt;Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/linux-sudo-per-command-authentication-path-restriction/&quot;&gt;Simple sudo settings to prevent unwanted Linux or UNIX privilege escalation: Per-command sudo authentication and path restriction&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gentoo-portage-emerge-http-or-socks-proxy/&quot;&gt;Using HTTP or SOCKS proxy with Gentoo Portage (emerge)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/securing-emacs-dir-locals-el-local-variables/&quot;&gt;Securing Emacs .dir-locals.el and local variables&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/measuring-emacs-startup-time/&quot;&gt;Measuring Emacs startup time more accurately than the built-in emacs-init-time&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/command-line-tool-to-configure-xfce-4-programmatically/&quot;&gt;Configure XFCE 4 programmatically with the help of watch-xfce-xfconf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ergonomic-workstation/&quot;&gt;My Ergonomic Workstation: Enhancing Focus, Comfort, and Efficiency&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-arch-linux-from-debian-system-ubuntu-linux-mint/&quot;&gt;Installing Arch Linux onto a separate partition from an existing Debian-based distribution (Ubuntu, Debian, Linux Mint...), without using the Arch Linux installation media&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gnome-shell-extensions-to-install-from-apt-debian-repositories/&quot;&gt;13 Useful GNOME Shell Extensions for a Better Desktop Experience (Available in the official Debian repositories or on the GNOME Extensions website for other distributions)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/pathaction/&quot;&gt;Pathaction | A universal Makefile for any file in the filesystem: Rule-driven commands for any file or directory&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-role-reniced/&quot;&gt;ansible-role-reniced - An Ansible role that configures reniced&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-role-auto-upgrade-an-ansible-role-that-automates-upgrading-linux-operating-systems/&quot;&gt;ansible-role-auto-upgrade - Ansible role for automated upgrades of Linux systems&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/google-home-matter-sensor-announcing-door-opened-closed/&quot;&gt;Google Home Script for announcing door open and close events using Matter door/window sensors&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/update-iptables-linux-firewall/&quot;&gt;update-iptables - A low-level Linux firewall for advanced users&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/fix-aqara-smart-hub-m3-volume-induced-reboots/&quot;&gt;Fixing Aqara Smart Hub M3 High Volume System Crashes and Reboots&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/wordpress-disable-xml-rpc/&quot;&gt;Disabling XML-RPC in WordPress for Security and Performance&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded>
</item>
<item>
<title>Simple sudo settings to prevent unwanted Linux or UNIX privilege escalation: Per-command sudo authentication and path restriction</title>
<link>https://www.jamescherti.com/linux-sudo-per-command-authentication-path-restriction/</link>
<guid isPermaLink="false">FZVv5EpkWr1yARTiyzUJ4Nibwjrs8iYzPcaGmA==</guid>
<pubDate>Tue, 06 Oct 2026 10:01:55 +0000</pubDate>
<description>The default sudo configuration caches successful authentication using a timestamp, allowing commands to execute without a password prompt for a limited period. This can cause security risks, such as local privilege escalation if an attacker accesses an unlocked terminal session or if a malicious script automatically escalates its own privileges within the cached timeframe. Additionally, restricting the execution path ensures that sudo only executes verified, system-installed packages. Here is...</description>
<content:encoded>&lt;p&gt;The default &lt;code&gt;sudo&lt;/code&gt; configuration caches successful authentication using a timestamp, allowing commands to execute without a password prompt for a limited period. This can cause security risks, such as local privilege escalation if an attacker accesses an unlocked terminal session or if a malicious script automatically escalates its own privileges within the cached timeframe.&lt;/p&gt;&lt;p&gt;Additionally, restricting the execution path ensures that &lt;code&gt;sudo&lt;/code&gt; only executes verified, system-installed packages.&lt;/p&gt;&lt;p&gt;Here is how to configure &lt;code&gt;sudo&lt;/code&gt; to require per-command authentication and restrict the execution path for commands.&lt;/p&gt;&lt;h2&gt;Edit the sudoers file&lt;/h2&gt;&lt;p&gt;Start modifying the &lt;code&gt;/etc/sudoers&lt;/code&gt; configuration file by using the following command as root:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;visudo&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Editing &lt;code&gt;/etc/sudoers&lt;/code&gt; file using &lt;code&gt;visudo&lt;/code&gt; locks the file and checks the syntax before saving changes.&lt;/p&gt;&lt;h2&gt;Requiring password authentication for every sudo command&lt;/h2&gt;&lt;p&gt;Set &lt;code&gt;timestamp_timeout&lt;/code&gt; to zero in the &lt;code&gt;/etc/sudoers&lt;/code&gt; file to enforce per-command authentication:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;Defaults timestamp_timeout=0&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;The benefit is that an attacker accessing an unlocked terminal after a legitimate &lt;code&gt;sudo&lt;/code&gt; command cannot reuse that authorization. For example, if a system administrator runs &lt;code&gt;sudo apt update&lt;/code&gt; and temporarily steps away from their desk without locking the screen, a malicious insider cannot walk up to the active terminal and type &lt;code&gt;sudo cat /etc/shadow&lt;/code&gt; to extract password hashes, as the system will immediately demand the password again.&lt;/p&gt;&lt;p&gt;Additionally, it prevents both background processes and user-executed programs from exploiting a cached session to automatically escalate their privileges:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In a legitimate but unintended context, a user might run a standard development command like &lt;code&gt;npm install&lt;/code&gt; or &lt;code&gt;make&lt;/code&gt; on a third-party project. If the project contains build hooks configured to modify system directories or install global binaries, an active &lt;code&gt;sudo&lt;/code&gt; session allows the script to silently execute these elevated changes, completely bypassing the user&amp;#39;s opportunity to review or approve the action.&lt;/li&gt;&lt;li&gt;In a malicious context, a script running silently in the background could monitor for an active &lt;code&gt;sudo&lt;/code&gt; timestamp. Once the user legitimately authenticates, the script exploits the cached token, for example, to append an attacker&amp;#39;s SSH key to &lt;code&gt;/root/.ssh/authorized_keys&lt;/code&gt; without generating a visible password prompt. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The tradeoff is requiring repeated password entry when running several privileged commands interactively. &lt;/p&gt;&lt;h2&gt;Restricting the execution path&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;secure_path&lt;/code&gt; directive replaces the user&amp;#39;s &lt;code&gt;PATH&lt;/code&gt; with a fixed value during a &lt;code&gt;sudo&lt;/code&gt; execution:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;Defaults secure_path=&amp;quot;/usr/sbin:/usr/bin:/sbin:/bin&amp;quot;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Update these directories to match your operating system and local administrative tools.&lt;/p&gt;&lt;h2&gt;Validating the recommended configuration&lt;/h2&gt;&lt;p&gt;If you choose to modify files in &lt;code&gt;/etc/sudoers.d/&lt;/code&gt; instead of using the &lt;code&gt;visudo&lt;/code&gt; command, validate the configuration by running the following command as root to parse the sudo configuration files for syntax errors:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;visudo -c&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Conslusion&lt;/h2&gt;&lt;p&gt;These &lt;code&gt;sudo&lt;/code&gt; configurations provide explicit, deterministic control over privilege escalation. Forcing authentication for all elevated actions and locking the execution path to verified system directories eliminate the risk of cached credentials and manipulated environment variables. This ensures every command executed as root becomes an intentional, manually authorized event.&lt;/p&gt;&lt;div&gt;&lt;h3&gt;Related posts:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gentoo-linux-unlock-lvm-root-partition-at-boot-key-file-external-usb-stick/&quot;&gt;Gentoo Linux and Genkernel: Unlocking a LUKS Encrypted LVM Root Partition at Boot Time using a Key File stored on an External USB Drive&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/&quot;&gt;Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/the-jc-dotfiles-repository/&quot;&gt;jc-dotfiles - James Cherti&amp;#39;s Dotfiles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/script-update-arch-linux/&quot;&gt;Helper script to upgrade Arch Linux&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/command-line-tool-to-configure-xfce-4-programmatically/&quot;&gt;Configure XFCE 4 programmatically with the help of watch-xfce-xfconf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/creating-disk-image-unix-linux/&quot;&gt;Creating and Restoring a Gzip Compressed Disk Image with dd on Linux or UNIX systems&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/linux-cherry-mx-blue-emulator-mechanical-keyboards/&quot;&gt;Emulating Cherry MX Blue Mechanical Keyboard Sounds on Linux&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/running-large-language-models-with-ollama/&quot;&gt;Running Large Language Models locally with Ollama (compatible with Linux, macOS, and Windows)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/importance-of-backups/&quot;&gt;Why failing to create backups and test them lead to regret&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/change-default-gdm-login-monitor-gnome-multi-monitor/&quot;&gt;Linux: Setting the default GDM login monitor in a multi-monitor setup using GNOME display settings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-arch-linux-from-debian-system-ubuntu-linux-mint/&quot;&gt;Installing Arch Linux onto a separate partition from an existing Debian-based distribution (Ubuntu, Debian, Linux Mint...), without using the Arch Linux installation media&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gnome-shell-extensions-to-install-from-apt-debian-repositories/&quot;&gt;13 Useful GNOME Shell Extensions for a Better Desktop Experience (Available in the official Debian repositories or on the GNOME Extensions website for other distributions)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/pathaction/&quot;&gt;Pathaction | A universal Makefile for any file in the filesystem: Rule-driven commands for any file or directory&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/update-iptables-linux-firewall/&quot;&gt;update-iptables - A low-level Linux firewall for advanced users&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-xfce-settings/&quot;&gt;A Shell Script that Automates XFCE Desktop Configuration&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-gnome-settings/&quot;&gt;A Shell Script that Configures the GNOME Desktop Programmatically&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-gentoo-portage/&quot;&gt;jc-gentoo-portage - An opinionated, performance-oriented Gentoo Portage /etc/portage configuration&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/secure-fail2ban-ssh-linux/&quot;&gt;Protecting SSH with Fail2ban on Linux systems, such as Debian, Ubuntu, Arch Linux, Linux Mint, Debian, Kali Linux, raspbian, Gentoo, etc.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/install-debian-cubox-i/&quot;&gt;Installing Debian on a CuBox-i computer (CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro)&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded>
</item>
<item>
<title>Installing Debian on a CuBox-i computer (CuBox-i1, CuBox-i2, CuBox-i2eX, or CuBox-i4Pro)</title>
<link>https://www.jamescherti.com/install-debian-cubox-i/</link>
<guid isPermaLink="false">-N14yIz3W-KLz8BbJyQSWFHLjMQdOuLDH6PlKg==</guid>
<pubDate>Tue, 06 Oct 2026 10:01:55 +0000</pubDate>
<description>The CuBox-i is a series of compact, fanless computers, by SolidRun, that feature a cube-shaped enclosure. Installing Debian Linux on CuBox-i series computers, such as the CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro, requires specific bootloader preparation. After spending four hours troubleshooting multiple failed installations, I found the reliable solution documented here. This article details a deployment strategy using the Debian hd-media offline installation method over a serial con...</description>
<content:encoded>&lt;p&gt;The CuBox-i is a series of compact, fanless computers, by SolidRun, that feature a cube-shaped enclosure.&lt;/p&gt;&lt;p&gt;Installing Debian Linux on CuBox-i series computers, such as the CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro, requires specific bootloader preparation.&lt;/p&gt;&lt;p&gt;After spending four hours troubleshooting multiple failed installations, I found the reliable solution documented here. This article details a deployment strategy using the Debian &lt;em&gt;hd-media&lt;/em&gt; offline installation method over a serial console connection, avoiding the network-based installer and HDMI issues. After booting the installed Debian system, the network and other hardware work as expected.&lt;/p&gt;&lt;h2&gt;Requirements&lt;/h2&gt;&lt;p&gt;Computers:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A Linux computer used to prepare the storage media and access the CuBox serial console.&lt;/li&gt;&lt;li&gt;A CuBox-i series computer (CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Accessories:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Micro-USB Data Cable: A standard Micro-USB to USB-A cable capable of data transfer (not a charge-only cable). This connects the host computer to the CuBox micro-USB service port to access the serial console, enabling terminal access during boot and installation.&lt;/li&gt;&lt;li&gt;USB Flash Drive: A drive used to store the Debian ISO for offline installation, such as &amp;quot;debian-12.x.x-armhf-netinst.iso&amp;quot;.&lt;/li&gt;&lt;li&gt;MicroSD Card: Required to boot the Debian installer and will serve as the storage medium where Debian will be installed. A minimum of 4 GB is recommended.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Packages:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;screen: Install the &lt;em&gt;screen&lt;/em&gt;, to connect to &amp;quot;/dev/ttyUSB0&amp;quot;, using: &lt;code&gt;apt-get install screen&lt;/code&gt;&lt;/li&gt;&lt;li&gt;dosfstools: Install the mkfs.vfat command-line tool using &lt;code&gt;apt-get install dosfstools&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Known Debian installer issues on the CuBox-i computers&lt;/h2&gt;&lt;p&gt;Before beginning, it is important to understand why the Debian network-based installation method can fail on this hardware:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Network installer issues: Some Debian installer versions have had problems detecting or configuring the CuBox-i Ethernet interface.&lt;/li&gt;&lt;li&gt;HDMI display issues: The Debian installer can fail to provide a usable HDMI display on some CuBox-i models. Using the serial console avoids depending on HDMI output during installation.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The solution is to perform an offline installation using the &lt;em&gt;hd-media&lt;/em&gt; method while operating the system through a serial console over USB.&lt;/p&gt;&lt;h2&gt;Preparing the MicroSD card&lt;/h2&gt;&lt;p&gt;Requirement: A MicroSD card. This card is required to boot the Debian installer and will serve as the storage medium where Debian will be installed. A minimum of 4 GB is recommended.&lt;/p&gt;&lt;p&gt;The CuBox-i requires a device-specific U-Boot bootloader to initialize the hardware.&lt;/p&gt;&lt;p&gt;Download the following files:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;firmware.MX6_Cubox-i.img.gz&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;http://deb.debian.org/debian/dists/stable/main/installer-armhf/current/images/netboot/SD-card-images/firmware.MX6_Cubox-i.img.gz&quot;&gt;http://deb.debian.org/debian/dists/stable/main/installer-armhf/current/images/netboot/SD-card-images/firmware.MX6_Cubox-i.img.gz&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;partition.img.gz&lt;/strong&gt;&lt;br/&gt;&lt;a href=&quot;http://deb.debian.org/debian/dists/stable/main/installer-armhf/current/images/netboot/SD-card-images/partition.img.gz&quot;&gt;http://deb.debian.org/debian/dists/stable/main/installer-armhf/current/images/netboot/SD-card-images/partition.img.gz&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Note: The links above download both files from the Debian stable (&lt;code&gt;/stable/&lt;/code&gt;) version.&lt;/p&gt;&lt;p&gt;Then run the following commands as root to write the firmware and partition images directly to the SD card:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-bash&quot;&gt;zcat firmware.MX6_Cubox-i.img.gz partition.img.gz &amp;gt; /dev/sdX&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Warning:&lt;/strong&gt; This command will erase all data on &lt;code&gt;/dev/sdX&lt;/code&gt;. Verify that &lt;code&gt;/dev/sdX&lt;/code&gt; is the correct SD card device before running it.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;/dev/sdX&lt;/code&gt; with the exact target device identifier. (The SD card identifier will typically appear as &lt;code&gt;/dev/sdX&lt;/code&gt; for USB adapters or &lt;code&gt;/dev/mmcblkX&lt;/code&gt; for native readers.)&lt;/p&gt;&lt;p&gt;Finally, flush file system buffers to ensure all data is written to the device:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-shell&quot;&gt;sync&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;This creates the Debian installer image from the device-specific U-Boot portion and the installer partition image.&lt;/p&gt;&lt;h2&gt;Preparing the offline installation media (USB Flash Drive)&lt;/h2&gt;&lt;p&gt;Requirements:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A USB flash drive. A drive used to store the Debian ISO for offline installation, such as &amp;quot;debian-12.x.x-armhf-netinst.iso&amp;quot;.&lt;/li&gt;&lt;li&gt;A Linux computer used to prepare the storage media.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The &lt;em&gt;hd-media&lt;/em&gt; installer can use a Debian ISO image stored on a separate USB drive.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Step 1: &lt;/strong&gt;Download the netinst ISO image: &lt;a href=&quot;https://cdimage.debian.org/debian-cd/current/armhf/iso-cd/&quot;&gt;https://cdimage.debian.org/debian-cd/current/armhf/iso-cd/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;(For example, debian-x.x.x-armhf-netinst.iso, where x.x.x represents the current version number from the official image repository.)&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Copy the ISO as a normal file onto the USB filesystem. (Do not use block-level writing tools like &lt;code&gt;dd&lt;/code&gt; for this step.) Run the following as root:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-bash&quot;&gt;# Format the first partition of the USB drive to FAT32
mkfs.fat -F 32 /dev/sdX1

# Mount the newly formatted partition to a temporary directory
mkdir -p /mnt/debian-usb
mount /dev/sdX1 /mnt/debian-usb

# Copy the Debian netinst ISO file as a standard file into the FAT32 partition
cp debian-x.x.x-armhf-netinst.iso /mnt/debian-usb/

# Safely unmount the USB drive
umount /mnt/debian-usb

# Flush buffers to prevent data corruption on large file transfers
sync&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;The Debian installer can then locate and mount the ISO from the USB drive.&lt;/p&gt;&lt;p&gt;Note: The Debian &lt;em&gt;hd-media&lt;/em&gt; installer kernel on the MicroSD card must be the same release version as the kernel inside the .iso file. Mixing daily installer builds with stable ISO images will result in a kernel mismatch error. &lt;strong&gt;As a rule of thumb, if a stable Debian (current) ISO is downloaded, the &lt;em&gt;hd-media&lt;/em&gt; kernel should also be downloaded from the corresponding stable Debian release rather than from the daily installer builds.&lt;/strong&gt;&lt;/p&gt;&lt;h2&gt;Reboot and start installing Debian&lt;/h2&gt;&lt;p&gt;With both storage media prepared:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Insert the prepared MicroSD card into the MicroSD card slot on the CuBox-i.&lt;/li&gt;&lt;li&gt;Insert the FAT32 USB flash drive containing the Debian .iso file into one of the on the CuBox-i USB ports.&lt;/li&gt;&lt;li&gt;Ensure the micro-USB data cable connects the CuBox-i service port to the host Linux machine.&lt;/li&gt;&lt;li&gt;Unplug and plug the power adapter into the CuBox-i.&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Accessing the serial console&lt;/h2&gt;&lt;p&gt;Requirement: &lt;strong&gt;A Micro-USB data cable.&lt;/strong&gt; A standard Micro-USB to USB-A cable capable of data transfer. This connects the host computer to the CuBox micro-USB service port to access the serial console.&lt;/p&gt;&lt;p&gt;Early boot graphics can fail to provide usable HDMI output on some CuBox-i configurations. Instead, use the built-in serial interface via the micro-USB port to access the terminal output.&lt;/p&gt;&lt;p&gt;Run the following on the Linux host connected to the CuBox-i through a Micro-USB cable to access the CuBox serial interface:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-bash&quot;&gt;screen /dev/ttyUSB0 115200&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;(To exit the screen session safely: press Ctrl+A, release, press uppercase K, press Y)&lt;/p&gt;&lt;p&gt;The serial console provides direct, text-based access to early kernel panic messages and hardware initialization logs. The interface is strictly command-line.&lt;/p&gt;&lt;p&gt;Note: Disconnecting the HDMI cable is recommended during setup. HDMI cables carry a 5V line that can backfeed into the CuBox power regulator, causing an &amp;quot;error enabling vbus supply&amp;quot; warning and halting the boot sequence.&lt;/p&gt;&lt;h2&gt;The Debian Installer: Navigating the installation steps&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;Locale and keyboard: Select the preferred language, country, and keyboard layout.&lt;/li&gt;&lt;li&gt;Missing firmware prompt: If the installer reports missing firmware, select No. The installer can then continue with the offline installation and search local storage for the Debian .iso file.&lt;/li&gt;&lt;li&gt;Network setup: If prompted to configure the network, select the option to configure the network later or proceed without a network connection. &lt;em&gt;(Some Debian installer versions have had problems detecting or configuring the CuBox-i Ethernet interface. The hd-media method avoids depending on network access during installation by providing the Debian ISO locally. The Debian installer can locate the ISO on a separate USB storage device and use it to obtain the installation files. This allows the installation to proceed without relying on the CuBox-i Ethernet interface during the installer stage. Network connectivity after installation depends on the installed kernel, drivers, firmware, and configuration.)&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Partition disks: At the partitioning screen, choose &amp;quot;&lt;strong&gt;Guided - use entire disk&lt;/strong&gt;&amp;quot; and select the MicroSD card. (The Debian installer runs from system memory after startup and that existing partitions on the installation card can be deleted or replaced.)&lt;/li&gt;&lt;li&gt;Software selection: Select standard system utilities.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;When the installer reaches the &amp;quot;Installation complete&amp;quot; screen:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Remove the USB flash drive from the CuBox-i.&lt;/li&gt;&lt;li&gt;Select Continue to reboot the CuBox-i.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The CuBox-i will reboot and load the Debian operating system from the MicroSD card.&lt;/p&gt;&lt;h2&gt;Installing the CuBox-i firmware&lt;/h2&gt;&lt;p&gt;After installing Debian on the CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro, additional firmware files are required for Wi-Fi and hardware-accelerated video decoding.&lt;/p&gt;&lt;p&gt;The VPU requires proprietary firmware to operate, and the Wi-Fi module requires symlinking files from an official Debian package. This article explains how to configure them.&lt;/p&gt;&lt;p&gt;Read the following article:&lt;br/&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-firmware-debian-linux-cubox-i1-i2-i2ex-i4pro/&quot;&gt;&lt;strong&gt;Installing CuBox i firmware on Debian Linux (CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;h3&gt;Related posts:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/bios-setting-performance-lenovo-thinkpad-t-w-x-series/&quot;&gt;BIOS settings for performance on older ThinkPads, such as T420, T420s, T520, W520, X220, T430...&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-firmware-debian-linux-cubox-i1-i2-i2ex-i4pro/&quot;&gt;Installing CuBox-i firmware on Debian Linux (CuBox-i1, CuBox-i2, CuBox-i2eX, or a CuBox-i4Pro)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-arch-linux-from-debian-system-ubuntu-linux-mint/&quot;&gt;Installing Arch Linux onto a separate partition from an existing Debian-based distribution (Ubuntu, Debian, Linux Mint...), without using the Arch Linux installation media&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/&quot;&gt;Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gnome-shell-extensions-to-install-from-apt-debian-repositories/&quot;&gt;13 Useful GNOME Shell Extensions for a Better Desktop Experience (Available in the official Debian repositories or on the GNOME Extensions website for other distributions)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/secure-fail2ban-ssh-linux/&quot;&gt;Protecting SSH with Fail2ban on Linux systems, such as Debian, Ubuntu, Arch Linux, Linux Mint, Debian, Kali Linux, raspbian, Gentoo, etc.&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/the-jc-dotfiles-repository/&quot;&gt;jc-dotfiles - James Cherti&amp;#39;s Dotfiles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/emacs-dir-locals-add-path-to-pythonpath/&quot;&gt;Emacs .dir-locals.el - Add project path to $PYTHONPATH (Python Development in Emacs)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/command-line-tool-to-configure-xfce-4-programmatically/&quot;&gt;Configure XFCE 4 programmatically with the help of watch-xfce-xfconf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gentoo-linux-unlock-lvm-root-partition-at-boot-key-file-external-usb-stick/&quot;&gt;Gentoo Linux and Genkernel: Unlocking a LUKS Encrypted LVM Root Partition at Boot Time using a Key File stored on an External USB Drive&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/script-update-arch-linux/&quot;&gt;Helper script to upgrade Arch Linux&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/arch-linux-keep-kernel-modules-during-upgrade/&quot;&gt;Arch Linux: Preserving the kernel modules of the currently running kernel during and after an upgrade&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/running-large-language-models-with-ollama/&quot;&gt;Running Large Language Models locally with Ollama (compatible with Linux, macOS, and Windows)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/importance-of-backups/&quot;&gt;Why failing to create backups and test them lead to regret&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/change-default-gdm-login-monitor-gnome-multi-monitor/&quot;&gt;Linux: Setting the default GDM login monitor in a multi-monitor setup using GNOME display settings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/pathaction/&quot;&gt;Pathaction | A universal Makefile for any file in the filesystem: Rule-driven commands for any file or directory&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-xfce-settings/&quot;&gt;A Shell Script that Automates XFCE Desktop Configuration&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-gnome-settings/&quot;&gt;A Shell Script that Configures the GNOME Desktop Programmatically&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-gentoo-portage/&quot;&gt;jc-gentoo-portage - An opinionated, performance-oriented Gentoo Portage /etc/portage configuration&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded>
</item>
<item>
<title>Protecting SSH with Fail2ban on Linux systems, such as Debian, Ubuntu, Arch Linux, Linux Mint, Debian, Kali Linux, raspbian, Gentoo, etc.</title>
<link>https://www.jamescherti.com/secure-fail2ban-ssh-linux/</link>
<guid isPermaLink="false">nAUrNqKTIHjyEjjoKMVW-vcfL6jvgYDnkv63Jw==</guid>
<pubDate>Tue, 06 Oct 2026 10:01:55 +0000</pubDate>
<description>Brute-force attacks against SSH frequently target internet facing Linux systems, such as Debian, Ubuntu, Arch Linux, Linux Mint, Kali Linux, Raspberry Pi OS (Raspbian), Gentoo, etc. Fail2ban resolves this by monitoring authentication logs and dynamically updating firewall rules to block IP addresses that show malicious behavior such as repeated failed login attempts. This article covers configuring custom jail parameters and applying the rules to protect SSH. When does Fail2ban actually impro...</description>
<content:encoded>&lt;p&gt;Brute-force attacks against SSH frequently target internet facing Linux systems, such as Debian, Ubuntu, Arch Linux, Linux Mint, Kali Linux, Raspberry Pi OS (Raspbian), Gentoo, etc. &lt;strong&gt;Fail2ban&lt;/strong&gt; resolves this by monitoring authentication logs and dynamically updating firewall rules to block IP addresses that show malicious behavior such as repeated failed login attempts.&lt;/p&gt;&lt;p&gt;This article covers configuring custom jail parameters and applying the rules to protect SSH.&lt;/p&gt;&lt;h2&gt;When does Fail2ban actually improve SSH security?&lt;/h2&gt;&lt;p&gt;The real value of Fail2ban depends on the authentication model. If a server allows password authentication, Fail2ban reduces exposure to automated brute-force attacks by limiting how many authentication attempts an attacker can make from a given IP address.&lt;/p&gt;&lt;p&gt;If a server &lt;strong&gt;enforces key-only authentication (highly recommended) and disables root logins&lt;/strong&gt;, password guessing is no longer an effective attack method. Even so, public-key authentication does not prevent resource exhaustion. Botnets frequently scan exposed SSH ports, and even with password authentication disabled, the SSH server still has to accept incoming TCP connections and process the initial SSH protocol handshake before rejecting the attempt.&lt;/p&gt;&lt;p&gt;Fail2ban addresses this by dynamically updating firewall rules to block any IP address that exceeds a configured threshold of failed attempts. Blocking repeat offenders at the network layer reduces the CPU load of handling malicious SSH handshakes and keeps authentication logs clean. It also generates explicit ban events, providing an audit trail of abusive IP addresses without cluttering logs with background noise.&lt;/p&gt;&lt;h2&gt;Installing packages&lt;/h2&gt;&lt;p&gt;The initial step requires installing the &lt;code&gt;fail2ban&lt;/code&gt;, the daemon responsible for parsing logs and managing bans.&lt;/p&gt;&lt;p&gt;On Debian-based systems, &lt;code&gt;fail2ban&lt;/code&gt; can be installed with:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;apt-get install fail2ban&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;For other distributions, install &lt;code&gt;fail2ban&lt;/code&gt; using the package manager.&lt;/p&gt;&lt;h2&gt;Configuring jail.local&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;fail2ban&lt;/code&gt; package ships with &lt;code&gt;/etc/fail2ban/jail.conf&lt;/code&gt; by default. Do not edit this file directly. Instead, create &lt;code&gt;/etc/fail2ban/jail.local&lt;/code&gt;. Using jail.local ensures package upgrades do not overwrite your configurations. (Fail2ban reads .conf files first, followed by .local files, which override the default values.)&lt;/p&gt;&lt;p&gt;Create the &lt;code&gt;/etc/fail2ban/jail.local&lt;/code&gt; file with the following content:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;[DEFAULT]
# Uncomment to use journalctl to find SSH authentication attempts
# backend = systemd

# The duration a host is banned (supports seconds or abbreviations like 1h)
bantime = 1h

# Number of failures (e.g., failed SSH login attempts) before a host is banned
maxretry = 5

# A host is banned if it has generated &amp;#39;maxretry&amp;#39; attempts during the last &amp;#39;findtime&amp;#39;
findtime = 10m

# Never ban these ip addresses
ignoreip = 127.0.0.1/8 ::1

[sshd]
enabled = true
port = ssh
filter = sshd&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;To prevent accidental lockouts, add trusted IP addresses, CIDR ranges, or hostnames to &lt;code&gt;ignoreip&lt;/code&gt;. Fail2ban skips rule enforcement for these addresses. Separate multiple entries with spaces (e.g., &lt;code&gt;ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 203.0.113.40&lt;/code&gt;). Always include management workstations, VPN gateways, and jump hosts before enforcing bans.&lt;/p&gt;&lt;h2&gt;Managing repeat offenders with the recidive jail&lt;/h2&gt;&lt;p&gt;Configuring the &lt;code&gt;recidive&lt;/code&gt; jail handles persistent attackers who return after their initial ban expires by monitoring the Fail2ban log itself and applying longer, stricter bans to IP addresses repeatedly banned by other jails.&lt;/p&gt;&lt;p&gt;Add the following to &lt;code&gt;/etc/fail2ban/jail.local&lt;/code&gt; to extend the ban for persistent abusers:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;[recidive]
enabled = true

# Monitor the fail2ban log file for repeated bans
backend = polling
logpath = /var/log/fail2ban.log

banaction = %(banaction_allports)s

# Ban repeat offenders for 1 week
bantime = 1w

# Look for repeat bans over the last 1 day
findtime = 1d

# Trigger after 5 previous bans
maxretry = 5&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Applying the configuration&lt;/h2&gt;&lt;p&gt;After modifying the &lt;code&gt;/etc/fail2ban/jail.local&lt;/code&gt; file, restart the daemon to apply the new rules:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;systemctl restart fail2ban&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Verifying the status&lt;/h2&gt;&lt;p&gt;This reports the status of the &lt;code&gt;sshd&lt;/code&gt; jail, including the current number of banned IP addresses:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;fail2ban-client status sshd&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;How to unblock an IP address?&lt;/h2&gt;&lt;p&gt;To unblock an IP address managed by Fail2bans ssh jail, use:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;fail2ban-client set sshd unbanip 8.8.8.8&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;Alternatively, you can use the following to remove an IP address from all active jails simultaneously:&lt;/p&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;fail2ban-client unban 8.8.8.8&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;Beyond Fail2ban&lt;/h2&gt;&lt;p&gt;While Fail2ban reduces automated SSH brute-force attacks, it is reactive and insufficient as a standalone security strategy. Since Fail2ban reacts to events after they have been recorded by the monitored service or log source, the underlying attack surface remains exposed to initial probes and attackers that rotate IP addresses or stay below the configured thresholds.&lt;/p&gt;&lt;p&gt;Rather than treating Fail2ban as a complete solution, It is recommended to implement a layered defense architecture that includes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Moving the actual SSH daemon off public-facing interfaces,&lt;/li&gt;&lt;li&gt;enforcing key-only authentication,&lt;/li&gt;&lt;li&gt;disabling root logins,&lt;/li&gt;&lt;li&gt;setting up a default-deny firewall,&lt;/li&gt;&lt;li&gt;implementing multi-factor authentication,&lt;/li&gt;&lt;li&gt;using a VPN,&lt;/li&gt;&lt;li&gt;hardening cryptographic algorithms,&lt;/li&gt;&lt;li&gt;deploying a decoy honeypot (e.g., Cowrie),&lt;/li&gt;&lt;li&gt;Limiting malicious attempts using OpenSSH&amp;#39;s native features, such as &lt;code&gt;PerSourcePenalties&lt;/code&gt; and &lt;code&gt;MaxStartups&lt;/code&gt; to reduce attack surface,&lt;/li&gt;&lt;li&gt;and configuring &lt;code&gt;sshd&lt;/code&gt; to listen on a non-standard port, such as 22000 instead of the default 22. (This is another method to reduce automated scanning. Many botnets are programmed to look exclusively for open port 22. While changing the port is security by obscurity and will not defeat a dedicated attacker, it drops the volume of opportunistic background traffic hitting your server.)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;h3&gt;Related posts:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/the-jc-dotfiles-repository/&quot;&gt;jc-dotfiles - James Cherti&amp;#39;s Dotfiles&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ergonomic-workstation/&quot;&gt;My Ergonomic Workstation: Enhancing Focus, Comfort, and Efficiency&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-arch-linux-from-debian-system-ubuntu-linux-mint/&quot;&gt;Installing Arch Linux onto a separate partition from an existing Debian-based distribution (Ubuntu, Debian, Linux Mint...), without using the Arch Linux installation media&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/gnome-shell-extensions-to-install-from-apt-debian-repositories/&quot;&gt;13 Useful GNOME Shell Extensions for a Better Desktop Experience (Available in the official Debian repositories or on the GNOME Extensions website for other distributions)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/emacs-dir-locals-add-path-to-pythonpath/&quot;&gt;Emacs .dir-locals.el - Add project path to $PYTHONPATH (Python Development in Emacs)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/script-update-arch-linux/&quot;&gt;Helper script to upgrade Arch Linux&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/how-to-install-debian-using-arch-linux-or-gentoo/&quot;&gt;Installing Debian onto a separate partition from an existing distribution, such as Arch Linux or Gentoo, without using the Debian installer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/emacs-quick-sdcv-offline-dictionary/&quot;&gt;quick-sdcv.el - Emacs offline dictionary using &amp;#39;sdcv&amp;#39;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-role-reniced/&quot;&gt;ansible-role-reniced - An Ansible role that configures reniced&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/make-vim-edit-or-diff-files-from-outside-vim-from-shell-bash-zsh/&quot;&gt;vim-client - send commands to the Vim editor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/command-line-tool-to-configure-xfce-4-programmatically/&quot;&gt;Configure XFCE 4 programmatically with the help of watch-xfce-xfconf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/ansible-install-gitolite-linux/&quot;&gt;ansible-role-gitolite - An Ansible role that automates the installation and configuration of Gitolite, a Git repository management system&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/running-large-language-models-with-ollama/&quot;&gt;Running Large Language Models locally with Ollama (compatible with Linux, macOS, and Windows)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/importance-of-backups/&quot;&gt;Why failing to create backups and test them lead to regret&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/change-default-gdm-login-monitor-gnome-multi-monitor/&quot;&gt;Linux: Setting the default GDM login monitor in a multi-monitor setup using GNOME display settings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/update-iptables-linux-firewall/&quot;&gt;update-iptables - A low-level Linux firewall for advanced users&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-xfce-settings/&quot;&gt;A Shell Script that Automates XFCE Desktop Configuration&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/jc-gnome-settings/&quot;&gt;A Shell Script that Configures the GNOME Desktop Programmatically&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/&quot;&gt;Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT)&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;</content:encoded>
</item>
<item>
<title>Fixing the throttling that slow down Thinkpad laptops, such as the Lenovo Thinkpad T420s (BD PROCHOT) | James Cherti</title>
<link>https://www.jamescherti.com/prochot-lenovo-thinkpad-t420s-throttled/</link>
<enclosure type="image/jpeg" length="0" url="https://jamescherti.com/misc/og-james-cherti.jpg"></enclosure>
<guid isPermaLink="false">ev8jeDl3GNZNhfFGq7JAwywipOJwPiYIOoTY1A==</guid>
<pubDate>Tue, 06 Oct 2026 10:01:55 +0000</pubDate>
<description>Even after configuring Linux on a Lenovo ThinkPad, such as the Thinkpad T420s, the laptop can still experience unexplained CPU throttling that degrades perfo...</description>
<content:encoded>&lt;div&gt;&lt;br/&gt;&lt;strong&gt;Author:&lt;/strong&gt; James Cherti&lt;br/&gt;&lt;strong&gt;Share: &lt;/strong&gt;&lt;a href=&quot;https://news.ycombinator.com/submitlink?u=https%3A%2F%2Fwww.jamescherti.com%2Fprochot-lenovo-thinkpad-t420s-throttled%2F&amp;amp;t=Fixing%20the%20throttling%20that%20slow%20down%20Thinkpad%20laptops%2C%20such%20as%20the%20Lenovo%20Thinkpad%20T420s%20%28BD%20PROCHOT%29&quot;&gt;&lt;span&gt;Hacker News&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;https://x.com/intent/post?text=Fixing+the+throttling+that+slow+down+Thinkpad+laptops%2C+such+as+the+Lenovo+Thinkpad+T420s+%28BD+PROCHOT%29&amp;amp;url=https%3A%2F%2Fwww.jamescherti.com%2Fprochot-lenovo-thinkpad-t420s-throttled%2F&quot;&gt;&lt;span&gt;X&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;https://www.reddit.com/submit?url=https%3A%2F%2Fwww.jamescherti.com%2Fprochot-lenovo-thinkpad-t420s-throttled%2F&amp;amp;title=Fixing+the+throttling+that+slow+down+Thinkpad+laptops%2C+such+as+the+Lenovo+Thinkpad+T420s+%28BD+PROCHOT%29&quot;&gt;&lt;span&gt;Reddit&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;https://www.linkedin.com/shareArticle/?mini=true&amp;amp;url=https%3A%2F%2Fwww.jamescherti.com%2Fprochot-lenovo-thinkpad-t420s-throttled%2F&quot;&gt;&lt;span&gt;LinkedIn&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Even after &lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;configuring Linux on a Lenovo ThinkPad, such as the Thinkpad T420s&lt;/a&gt;, the laptop can still experience unexplained CPU throttling that degrades performance.&lt;/p&gt;&lt;p&gt;A common cause is an externally asserted BD PROCHOT (Bi-Directional Processor Hot). While standard PROCHOT is initiated internally by the processor when it overheats, BD-PROCHOT allows other components, such as power supply sensors or battery circuitry, to send a hardware signal directly to the CPU, which triggers processor throttling regardless of actual CPU core temperatures.&lt;/p&gt;&lt;h2&gt;What does BD-PROCHOT do to the Lenovo ThinkPad laptops?&lt;/h2&gt;&lt;p&gt;The CPU clock speed is locked at a low frequency, which causes severe system lag during basic desktop tasks such as video playback or web browsing. Because BD-PROCHOT can be asserted by power management sensors rather than CPU temperature, the CPU remains throttled even when core temperatures are normal.&lt;/p&gt;&lt;h2&gt;How to check if PROCHOT is enabled?&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;msr-tools&lt;/code&gt; package&lt;/li&gt;



&lt;li&gt;Load the msr Linux module using: &lt;code&gt;modprobe msr&lt;/code&gt; &lt;/li&gt;



&lt;li&gt;Run the following command:&lt;/li&gt;
&lt;/ol&gt;&lt;pre&gt;&lt;span&gt;&lt;code class=&quot;hljs language-plaintext&quot;&gt;echo -n &amp;quot;PROCHOT &amp;quot;; (( 0x$(rdmsr -p0 0x1fc) &amp;amp; 1 )) &amp;amp;&amp;amp; echo &amp;quot;enabled&amp;quot; || echo &amp;quot;disabled&amp;quot;&lt;/code&gt;&lt;/span&gt;&lt;/pre&gt;&lt;h2&gt;What causes BD-PROCHOT and throttling on the Lenovo ThinkPad laptops?&lt;/h2&gt;&lt;p&gt;Several hardware, power supply, and thermal conditions trigger BD-PROCHOT or general CPU throttling on the Lenovo ThinkPad laptops:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Using underpowered or aging power adapters or an unverified third-party charger.&lt;/li&gt;



&lt;li&gt;Using a heavily degraded or failing battery, which can misreport electrical metrics to the embedded controller.&lt;/li&gt;



&lt;li&gt;Failing hardware or bad sensors on the motherboard can incorrectly signal a thermal or power fault.&lt;/li&gt;



&lt;li&gt;Old, dried-up thermal paste on the CPU.&lt;/li&gt;



&lt;li&gt;Accumulated dust in the fan assembly.&lt;/li&gt;



&lt;li&gt;Using an underpowered 65W (OUTPUT: 20V, 3.25 A) charger instead of the 90W power adapter (OUTPUT: 20V, 4.5A).&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Solution: throttled&lt;/h2&gt;&lt;p&gt;One solution is to use the the &lt;code&gt;throttled&lt;/code&gt; daemon, which writes directly to CPU and chipset registers:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/erpalma/throttled&quot;&gt;Download and install throttled from the &amp;#39;throttled&amp;#39; repository&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The primary configuration file is located at &lt;code&gt;/etc/throttled.conf&lt;/code&gt;. It contains separate profiles for power limits, update intervals, and temperature targets.&lt;/p&gt;&lt;p&gt;Note: The &lt;code&gt;thermald&lt;/code&gt; daemon can conflict with &lt;code&gt;throttled&lt;/code&gt; by applying its own temperature policy.&lt;/p&gt;&lt;h2&gt;Similar articles&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;



&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/bios-setting-performance-lenovo-thinkpad-t-w-x-series/&quot;&gt;BIOS settings for Lenovo ThinkPad performance (T, W, and X series, such as T420, T420s, T520, X220, W520, T430...)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;

&lt;h3&gt;Related posts:&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/linux-sudo-per-command-authentication-path-restriction/&quot;&gt;Simple sudo settings to prevent unwanted Linux or UNIX privilege escalation: Per-command sudo authentication and path restriction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/bios-setting-performance-lenovo-thinkpad-t-w-x-series/&quot;&gt;BIOS settings for performance on older ThinkPads, such as T420, T420s, T520, W520, X220, T430...&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/the-jc-dotfiles-repository/&quot;&gt;jc-dotfiles - James Cherti&amp;#39;s Dotfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/thinkpad-t420-t420s-configure-linux/&quot;&gt;Configuring Linux on a Lenovo ThinkPad T420s Laptop (Debian, Ubuntu, Linux Mint...)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/emacs-consult-speed-async-searche-grep-ripgrep-fd-find/&quot;&gt;Why Emacs Consult async searches feel slow and how to speed them up? (consult-fd, consult-find, consult-grep, consult-ripgrep...)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/command-line-tool-to-configure-xfce-4-programmatically/&quot;&gt;Configure XFCE 4 programmatically with the help of watch-xfce-xfconf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/script-update-arch-linux/&quot;&gt;Helper script to upgrade Arch Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/arch-linux-keep-kernel-modules-during-upgrade/&quot;&gt;Arch Linux: Preserving the kernel modules of the currently running kernel during and after an upgrade&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/linux-cherry-mx-blue-emulator-mechanical-keyboards/&quot;&gt;Emulating Cherry MX Blue Mechanical Keyboard Sounds on Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/importance-of-backups/&quot;&gt;Why failing to create backups and test them lead to regret&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/change-default-gdm-login-monitor-gnome-multi-monitor/&quot;&gt;Linux: Setting the default GDM login monitor in a multi-monitor setup using GNOME display settings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jamescherti.com/installing-arch-linux-from-debian-system-ubuntu-linux-mint/&quot;&gt;Installing Arch Linux onto a separate partition from an existing Debian-based distribution (Ubuntu, Debian, Linux Mint...), without using the Arch Linux installation media&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</content:encoded>
</item>
<item>
<title>Can a Twenty-Year-Old Computer Still Be Useful?</title>
<link>https://deadparrotbbs.com/can-a-twenty-year-old-computer-still-be-useful/</link>
<guid isPermaLink="false">LUoKS_9quTZWws89D0N1cM2ypKtcIy2wZ5W0ZA==</guid>
<pubDate>Mon, 05 Oct 2026 22:40:46 +0000</pubDate>
<description>A twenty-year-old computer can still be useful if you stop asking it to behave like a new one.</description>
<content:encoded>&lt;p&gt;A computer from 2006 is old now. That sounds obvious until you stop and do the math. A machine from that period may have shipped with Windows XP, maybe Windows Vista if it was unlucky, or some version of Mac OS X that is now a museum piece by modern support standards. On the Linux side, it may have been running a distribution from an era when wireless drivers still made people mutter at their desks.&lt;/p&gt;&lt;p&gt;Yet a surprising number of those machines still turn on. The screen may be dim. The battery may be useless. The hard drive may sound like it is auditioning for mechanical failure. But the keyboard works, the ports are still there, and the processor can still add numbers just as honestly as it did when the machine was new.&lt;/p&gt;&lt;p&gt;The better question is not whether a twenty-year-old computer is useful in the abstract. The better question is useful for what.&lt;/p&gt;&lt;p&gt;If the job is the modern commercial web, the answer gets rough quickly. Current browsers are heavy. Many sites assume current TLS support, recent JavaScript engines, hardware acceleration, video codecs, plenty of memory, and a processor that can keep up with pages written like desktop applications. A 2006 machine can sometimes be coaxed into loading those pages, especially with enough RAM and a lightweight Linux installation, but it is not going to feel young.&lt;/p&gt;&lt;p&gt;Security is the other hard limit. Running an unsupported operating system on the open Internet is asking for trouble. That does not mean the machine must be thrown away. It means the role needs to be chosen carefully. A twenty-year-old computer used for online banking, password management, main email, or account administration is a bad idea. A twenty-year-old computer used for writing, local tools, retro software, terminal access, or a contained lab is a different matter.&lt;/p&gt;&lt;p&gt;There is still plenty of useful work that does not require the heaviest parts of today’s web. A machine from that period can be a writing station. It can run a text editor, keep notes, read plain documents, manage a local archive, play older media files, run period games, connect to BBSes, SSH into newer systems, or serve as a terminal for machines doing the harder work elsewhere. In some cases it can run a lightweight desktop well enough for email, feeds, and simple browsing, as long as expectations stay grounded.&lt;/p&gt;&lt;p&gt;Linux can help, but Linux is not a time machine. A lightweight distribution may give old hardware a cleaner second life. Replacing a spinning hard drive with an SSD can make a dramatic difference, if the machine supports it. Adding RAM helps, up to the limits of the hardware. Cleaning dust from the cooling system can matter more than people expect. Still, there comes a point where the browser, the kernel, the graphics stack, or basic electrical age sets the boundary.&lt;/p&gt;&lt;p&gt;The good news is that usefulness does not have to mean daily-driver status. We have a bad habit of measuring every computer by whether it can be the one machine for everything. That is a narrow standard. A twenty-year-old laptop may be a poor main computer and an excellent distraction-free writing box. An old desktop may be silly for video editing and perfectly fine as a serial console, ham radio station, test machine, file sorting station, or retro gaming rig.&lt;/p&gt;&lt;p&gt;Old hardware is also useful because it teaches limits. Modern computers hide a lot behind speed. Wasteful software can survive because the machine underneath is fast enough to absorb the damage. On older hardware, waste becomes visible. A bloated web page stutters. A careless background service matters. A simple native program feels good because it respects the machine. That kind of feedback is educational.&lt;/p&gt;&lt;p&gt;There is a repair lesson too. Twenty-year-old computers often come from the last period when many machines were still reasonably serviceable. That was never universal, but it was common enough to matter. Screws were common. Drives and memory were reachable. Batteries were more likely to be replaceable. Ports were generous. Documentation existed. Compared with sealed modern devices, some older computers feel less polished and more honest. You can open them without feeling like you are violating a product manager’s wishes.&lt;/p&gt;&lt;p&gt;That does not mean keeping every old machine alive makes sense. Some are power-hungry. Some are unreliable. Some use aging capacitors, dying displays, brittle plastics, or storage that should not be trusted. Sometimes the right answer is to salvage parts, wipe the drive, recycle the machine properly, and move on. Sentiment is not a maintenance plan.&lt;/p&gt;&lt;p&gt;But useful old computers deserve a fair assessment. Start with the hardware. Does it boot reliably? Can it take more RAM? Is the storage healthy? Does it overheat? Are replacement parts available? Then look at the job. Does that job require current security patches? Does it require modern web services? Does it require high performance, or only patience and a keyboard? The answer usually becomes clear once the job is specific.&lt;/p&gt;&lt;p&gt;For me, the most interesting uses are the ones that respect the age of the machine. Use it as a writing system. Put a small Linux or BSD setup on it if the hardware allows. Keep it off important accounts. Let it talk to newer machines over SSH. Use it for old software that belongs on it. Use it to learn how much computing can still happen without a stack of subscriptions and background services.&lt;/p&gt;&lt;p&gt;A twenty-year-old computer can still be useful. It probably should not be asked to ignore the last twenty years of software inflation. Give it a job that fits, keep the risks contained, and it may still earn its place on the desk.&lt;/p&gt;</content:encoded>
</item>
<item>
<title>My 5 favorite Linux distros for security – and how they protect your privacy</title>
<link>https://www.zdnet.com/tech/most-secure-linux-distros/</link>
<guid isPermaLink="false">Wbk9tYtv88uftKKZfTm7VJn5cRUMVc_x3YI8AQ==</guid>
<pubDate>Mon, 05 Oct 2026 19:10:38 +0000</pubDate>
<description>If security is a top priority, you should consider one of these five Linux distributions. They’re all free to install and use.</description>
<content:encoded>If security is a top priority, you should consider one of these five Linux distributions. They’re all free to install and use.</content:encoded>
</item>
<item>
<title>Using docker-compose with Podman rootless — Elouworld</title>
<link>https://elou.world/en/tutorial/podman-docker-compose</link>
<enclosure type="image/jpeg" length="0" url="https://elou.world/assets/avatar.png"></enclosure>
<guid isPermaLink="false">h-pJfN8vQ9B25D1Ti4wiPGq_bbbkn5ZzqPwTDA==</guid>
<pubDate>Mon, 05 Oct 2026 16:33:07 +0000</pubDate>
<description>Podman is a daemonless Docker alternative for Linux that can run without root access. However, it is less well known that Podman can expose a UNIX-domain socket compatible with the Docker API. This makes it work with most tools in the Docker ecosystem, such as docker-compose.</description>
<content:encoded>&lt;h1&gt;Using docker-compose with Podman rootless&lt;/h1&gt;&lt;time&gt;2026-10-05 09:22:33 UTC&lt;/time&gt;&lt;p&gt;&lt;a href=&quot;https://podman.io&quot;&gt;Podman&lt;/a&gt; is a daemonless Docker alternative for Linux that can run without root access. However, it is less well known that Podman can expose a UNIX-domain socket compatible with the Docker API. This makes it work with most tools in the Docker ecosystem, such as docker-compose.&lt;/p&gt;&lt;p&gt;Podman uses a Linux feature called user namespaces. With this, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; user inside a container is mapped to your host user. Other UIDs and GIDs are mapped to the ranges defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/subuid&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/subgid&lt;/code&gt;, respectively.&lt;/p&gt;&lt;p&gt;This tutorial assumes that Podman and docker-compose are already installed, for example using your Linux distribution’s package manager.&lt;/p&gt;&lt;h1&gt;Enable and start the Podman socket&lt;/h1&gt;&lt;p&gt;To enable and start the Podman socket, run this command (as your user, not as root):&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1

systemctl --user enable --now podman.socket&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This command creates a UNIX-domain socket at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${XDG_RUNTIME_DIR}/podman/podman.sock&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;${XDG_RUNTIME_DIR}&lt;/code&gt; is a private &lt;em&gt;tmpfs&lt;/em&gt; automatically mounted for each user.&lt;/p&gt;&lt;p&gt;Note: The command requires a systemd session. If you are trying to run this command as another user, be aware that using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; is not supported, because it doesn’t create a systemd session. You can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;machinectl shell --uid=your-username&lt;/code&gt; (part of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-container&lt;/code&gt; package on some Linux distributions) if you are part of the &lt;em&gt;wheel&lt;/em&gt; group. Alternatively, log in as your user on a TTY or via SSH.&lt;/p&gt;&lt;h1&gt;Expose it as the Docker host&lt;/h1&gt;&lt;p&gt;Tools like docker-compose read the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOCKER_HOST&lt;/code&gt; environment variable. Set it to point to the Podman socket like this:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1

export DOCKER_HOST=&amp;quot;unix://${XDG_RUNTIME_DIR}/podman/podman.sock&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Add this line to your shell configuration (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt; for Zsh) to make it permanent.&lt;/p&gt;&lt;h1&gt;Use docker-compose&lt;/h1&gt;&lt;p&gt;You can now run docker-compose as usual:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1
2
3
4

docker-compose config
docker-compose up -d
docker-compose ps
docker-compose down --volumes&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Depending on your Linux distribution, docker-compose may be available as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker compose&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose&lt;/code&gt;, but it works the same way. You can add an alias in your shell:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1

alias docker-compose=&amp;#39;docker compose&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;h1&gt;Tips and tricks&lt;/h1&gt;&lt;h2&gt;Stop and disable rootful Docker&lt;/h2&gt;&lt;p&gt;If you have Docker installed but are not ready to uninstall it, you can stop and disable its systemd service by running (as root):&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1
2

systemctl disable --now docker.service docker.socket
rm -f /var/run/docker.sock&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Note: These commands do not erase Docker data.&lt;/p&gt;&lt;p&gt;If you change your mind, run this to start it again (as root):&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1

systemctl enable --now docker.service&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman&lt;/code&gt; command accepts the same arguments as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt;, but you can also keep using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker&lt;/code&gt; command if you prefer: it can read the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOCKER_HOST&lt;/code&gt; variable and talk to the Podman socket, just like docker-compose.&lt;/p&gt;&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman unshare&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;If you want to become &lt;em&gt;root&lt;/em&gt; without starting a container, you can use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman unshare&lt;/code&gt; command, which starts a new shell as &lt;em&gt;root&lt;/em&gt; (in a user namespace, not real host root), much like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo -i&lt;/code&gt;. You will then be able to manipulate files owned by container users (for example with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chown&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod&lt;/code&gt;).&lt;/p&gt;&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman mount&lt;/code&gt;&lt;/h2&gt;&lt;p&gt;You can access the files of a running container with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman mount&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;First, run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman unshare&lt;/code&gt;, then change directory to the path returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman mount container-name-or-id&lt;/code&gt;:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1
2

podman unshare
cd &amp;quot;$(podman mount container-name-or-id)&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;You will then be able to run your usual TUI editor to edit files in the container.&lt;/p&gt;&lt;h2&gt;Docker rootless&lt;/h2&gt;&lt;p&gt;If you are not ready to switch to Podman, Docker also supports a rootless installation. See &lt;a href=&quot;https://docs.docker.com/engine/security/rootless/&quot;&gt;their documentation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Once it is set up and started, you also need to set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOCKER_HOST&lt;/code&gt; environment variable:&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1

export DOCKER_HOST=&amp;quot;unix://${XDG_RUNTIME_DIR}/docker.sock&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, rootless Docker has no equivalent of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman unshare&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;podman mount&lt;/code&gt;, although you can achieve similar things with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unshare&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsenter&lt;/code&gt;.&lt;/p&gt;&lt;h2&gt;User lingering&lt;/h2&gt;&lt;p&gt;By default, Podman containers are stopped when the last systemd session of your user is closed.&lt;/p&gt;&lt;p&gt;To keep them running after you log out, enable user lingering for your user (as root):&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;pre&gt;&lt;code&gt;1

loginctl enable-linger your-username&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;h1&gt;See also&lt;/h1&gt;&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://lobste.rs/s/tpxwfe/using_docker_compose_with_podman&quot;&gt;Comments on Lobsters&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/containers/podman-compose&quot;&gt;Podman Compose&lt;/a&gt; (which evolved a lot since I last used it a few years ago)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://emersion.fr/blog/2025/using-podman-compose-and-buildkit/&quot;&gt;Using Podman, Compose and BuildKit&lt;/a&gt; by &lt;em&gt;emersion&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Latest edition: &lt;time&gt;2026-10-05 16:14:55 UTC&lt;/time&gt;&lt;/p&gt;&lt;p&gt;Copyright © 2026, Elouan Martinet (Exagone313) — This work is licensed under a &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0/&quot;&gt;Creative Commons Attribution-ShareAlike 4.0 International License&lt;/a&gt;.&lt;/p&gt;</content:encoded>
</item>
</channel>
</rss>
