Linux Magazine - December 2024 USA
Linux Magazine - December 2024 USA
DV S I D
IN
+
D E
Linux ransomware tool
Coding
with
Save time with AI-assisted
programming
ON THE COVER
26 changedetection.io 64 Off-Grid File Sharing
This cool tool will keep an eye on a web page You don’t need the Internet to share files. The next
and alert you to changes. time you’re off grid, stay connected using ownCloud
and a battery-powered Raspberry Pi Zero.
32 Linodas 74 Anki
Do you think Linux is immune to ransomware? Part of training is memorization, and flashcards
We take you inside the Linux version of the are a popular tool for memorizing facts. We
illusive DinodasRAT attack. introduce you to an app that lets you integrate
audio and visual cues into the flashcard format.
42 Tampermonkey 88 Legacy Video Games
Many users don’t realize you can modify web You’ve kept those classic video game CDs from
content on the fly as your browser reads it. your childhood in a drawer for all these years.
We’ll show you how. Isn’t it time you did something with them?
NEWS IN-DEPTH
8 News 26 Web Page Monitoring
• The Gnome Foundation Struggling to Stay Afloat Do you want an alert when a product is back in stock at your
• Thousands of Linux Servers Infected with Stealth Malware favorite online store? With changedetection.io, you can stay
Since 2021 up-to-date on website changes.
• Halcyon Creates Anti-Ransomware Protection for Linux
• Valve and Arch Linux Announce Collaboration 32 Linodas
• OSI and LPI Form Strategic Alliance Cybercriminals are increasingly discovering Linux and
• AlmaLinux Unveils New Hardware Certification adapting malware previously designed for Windows
Process systems. We take you inside the Linux version of a famous
• Wind River Introduces eLxr Pro Linux Solution Windows ransomware tool.
• Juno Tab 3 Launches with Ubuntu 24.04
38 Command Line – zoxide
12 Kernel News Zoxide, a modern version of cd, lets you navigate long
This month in Kernel News, Zack reports on when the directory paths with less typing.
process is the feature.
42 Tampermonkey
Even small changes in a web page can improve the browsing
COVER STORY experience. Your preferred web browser provides all the tools
you need to inject JavaScript to adapt the page. You just
16 Write Code with AI need a browser with its debugging tools, some knowledge
Artificial intelligence is increasingly supporting of scripting, and the browser extension Tampermonkey.
programmers in their daily work. How effective are these
tools? What are the dangers? And how can you benefit 48 Programming Snapshot – Go Interfaces
from AI-assisted development today? Using the Go Interface mechanism, Mike demonstrates its
practical application with a refresh program for local
copies of Git repositories.
REVIEW
22 Distro Walk – ArcoLinux
ArcoLinux, an Arch derivative, offers easier installs while 95 Back Issues 97 Call for Papers
educating users about Arch Linux along the way. 96 Events 98 Coming Next Month
MakerSpace pertinent facts for your next exam. Anki takes this
time-honored trick in a direction you never could
have imagined in the days of those classic 3x5 cards.
56 Embedded Rust
Rust, a potential successor to C/C++, claims to solve some 82 FOSSPicks
memory safety issues while maintaining high performance. Nate explores some top FOSS tools, including the latest
We look at Rust on embedded systems, where memory Gnome desktop, a slick 3D model viewer, LibreQuake, a
safety, concurrency, and security are equally important. neat currency converter, and much more.
@linux-magazine.com
@linux_pro
TWO TERRIFIC DISTROS
@linuxpromagazine
DOUBLE-SIDED DVD!
Linux Magazine SEE PAGE 6 FOR DETAILS
@linuxmagazine
Essentially, this collaboration will make it considerably easier for Arch Linux devel-
opers to do their jobs. Arch Linux project leader Levente Polyak stated (https://lists.
archlinux.org/archives/list/[email protected]/thread/RIZSKIBDSLY-
4S5J2E2STNP5DH4XZGJMR/ ), “These projects will follow our usual development and
consensus-building workflows. [RFCs] will be created for any wide-ranging changes.”
He continues, “Discussions on this mailing list as well as issue, milestone, and
epic planning in our GitLab will provide transparency and insight into the work. We
believe this collaboration will greatly benefit Arch Linux and are looking forward to
sharing further development on this mailing list as work progresses.”
This collaboration shouldn’t come as a surprise to anyone, given that SteamOS
3.0 is based on Arch Linux.
All projects funded by Valve will stick to Arch Linux’s development and consensus-
building workflows and will provide more transparency into the work being done.
that bcachefs is _definitely_ more “And yes, these _are_ solid, the
trustworthy than brtfs, in terms of ‘will rhashtable stuff was done months ago
this filesystem ever go unrecoverable or (minus the deadlock fix, that’s more re-
lose my data’ – I’ve seen many reports cent), and the rcu_pending stuff was
of people who’ve put it through the mostly done months ago as well, and
same situations where btrfs [fails]. I’ve _heavily_ tested (including using it as re-
ever seen people compare bcachefs’s placement backend for kvfree_rcu, which
robustness in positive terms vs. /xfs/; is the eventual goal there).
and that’s the result of a *hell* of a lot “And the genradix code is code that I
of work with the #1 goal of having a also wrote and maintain, and those are
robust filesystem that _never_ loses simple patches.”
data.” To which Linus merely quipped,
Although in the next breath, he did “What is to be gained by having release
add a public disclaimer: “Please don’t rules and a stable development environ-
rush out and switch to bcachefs just ment? I wonder.”
yet. I still have a backlog of bugs and Linus then replied to his own quip a
issues – some of them serious, as in few minutes later, saying:
your filessystem will go emergency “But seriously – thinking that ‘I
read only – and I don’t want people changed a thousand lines, there’s no
getting bit. There’s still a ton to do; I’m way that introduces new bugs’ is the
not taking EXPERIMENTAL off until at kind of thinking that I DO NOT WANT
least the fuzz testing for on disk cor- TO HEAR from a maintainer.
ruption is in play.” “What planet ARE you from? Stop
Kent also defended his work ethic being obtuse.”
and development practices, saying, Kent replied, “I’m not sending you
“Look, I’ve been doing this for a long anything here that isn’t a fix for a real
time, I’ve had people running my code issue.”
in production for a long time, and I’m At this point, stepping back for a mo-
working with my users on a daily basis ment, Linus offered a more thorough
to address issues. I don’t throw code explanation of his thinking:
over the wall; I do everything I can to “Kent, bugs happen.
support it and make sure it’s working “The number of bugs that happen in
well.” He added, “when I ship code, ‘bug fixes’ is in fact quite high. You
I’m _always_ weighing ‘how much do should see the stable tree discussions
we want this’ vs. ‘risk of regression/ when people get heated about the re-
risk in general’ – I’m not just throwing gressions introduced by fixes.
out whatever I feel like.” “This is, for example, why stable has
Kent went on to say, “Look, this is the the rule of fixes being small (which does
filesystem you’re all going to want to be get violated, but it is at least a goal: ‘It
running in – knock on wood – just a cannot be bigger than 100 lines, with
year or two, because I’m working to context’), because small fixes are easier
make it more robust and reliable than to think about and hopefully they have
xfs and ext4 (and yes, it will be).” fewer problems of their own.
However, in terms of bcachefs’s reli- “It’s also why my ‘development happens
ability, Linus replied plainly: before the merge window’ rule exists.
“I’ll believe that when there are major “If you have to do development to fix
distros that use it and you have lots of an old problem, it’s for the next merge
varied use. window. Exactly because new bugs hap-
“But it doesn’t even change the issue: pen. We want _stability_.
you aren’t fixing a regression, you are “The fixes after the merge window are
doing new development to fix some old supposed to be fixes for regressions, not
problem, and now you are literally edit- ‘oh, I noticed a long-standing problem,
ing non-bcachefs files too. and now I’m fixing that’.
“Enough is enough.” “But obviously the same kind of logic
This attitude seemed to perplex Kent. as for stable trees apply: if it’s a small ob-
He replied: vious fix that would be stable material
“What is to be gained by holding back *anyway*, then there is no reason to
fixes, if we’ve got every reason to believe wait for the next release and then just
that the fixes are solid? put it in the stable pile.
“So I do end up taking small fixes, currently stable and working for cus- processes’ vs. ‘weighing the situations
because at that point it is indeed a ‘it tomers and new development. Your and using your judgement’. There isn’t a
wouldn’t help to wait’ situation. work is excellent but *process* is right or wrong answer as to where on the
“But your pull requests haven’t been equally and sometimes even more im- spectrum we should be, we just all have
‘small fixes’. And I admit, I’ve let it slide. portant. Some of the other hats I’ve to use our brains.
You never saw the last pull request, when worn professionally include as a lead “No one is being jerks here, Linus and
I sighed, did a ‘git fetch’, and went C/C++ developer and as a product re- I are just sitting in different places with
through every commit just to see. And lease manager so I’ve learned from different perspectives. He has a responsi-
then did the pull for real. very painful experience that large proj- bility as someone managing a huge proj-
“This time I did the same. And came ects absolutely *must* have strict rules ect to enforce rules as he sees best, while
to the conclusion that no, this was not a for process. I’m sure you realize that. I have a responsibility to support users
series of small fixes any more.” Linus is not being a jerk about this. with working code, and to do that to the
To Linus’s “bugs happen” comment, Just a couple of months ago Linus had best of my abilities.”
Kent replied: to tell you the exact same thing he’s The discussion ended there. My own
“I _know_. telling you again here. And that wasn’t take on the situation is that Linus gen-
“Look, filesystem development is as the first time. Is your plan to just con- erally prefers to win an argument
high stakes as it gets. Normal kernel tinue to break the rules and do what- rather than enforce his position. He
development, you fuck up – you crash ever the heck you want until Linus may have a reputation for being mean
the machine, you lose some work, you stops bothering you? I don’t think and bombastic, but I believe that look-
reboot, people are annoyed but generally that’s a good plan. ing only at those snapshots tends to
it’s ok. “Since I’m already being blunt I’m miss what’s really going on. In general,
“In filesystem land, you can corrupt going to be even more blunt: you have a Linus loses patience when he feels the
data and not find out about it until serious problem working with others. In other person has had something clearly
weeks later, or _worse_. I’ve got stories to the past and in this thread I’ve read explained and is willfully refusing to
give people literal nightmares. Hell, that where you seem to imply that other get the point.
stuff has fueled my own nightmares for kernel developers are gatekeeping and So, since Kent seems to be honestly
years. You know how much grey my resist some of your ideas because you’ve disagreeing with Linus in this conver-
beard has now? created something that (in your opin- sation, I think it could go either way. I
“Which is why I have spent many years ion) is already better in some ways than wouldn’t be surprised if Linus, for ex-
of my life building a codebase and devel- some of things they’ve created. But from ample, accepts another big patch from
opment process where I can work produc- where I’m sitting the problems you’ve Kent and gives him another reminder
tively where I can not just catch but re- experienced are 90% because of *you*. that this needs to change. At the same
cover from pretty much any fuckup You’re an adult and you need to under- time, in this discussion, Linus did say
imaginable. stand that about yourself so you can do “enough is enough,” and that generally
“Because peace of mind is priceless….” something about it.” indicates that he’s about to enforce the
At this point in the conversation, Carl Kent got the final word of the conver- rules. To me, it really could go either
E. Thompson joined in, trying to bridge sation, replying: way at this point.
the gap. He said: “You guys are freaked out because Part of the problem is that many ker-
“Kent, I’m not a kernel developer I’m I’m moving quickly and you don’t have nel developers are really amazing, and
just a user that is impressed with visibility into my own internal process, there can be a certain amount of arro-
bcachefs, uses it on his personal systems, that’s all. gance that goes along with having such
and eagerly waits for new features. I am “I’ve got a test [cluster], a community amazing skills and abilities. Kent
one of the users who’s been using testing my code before I send it to would not be the first Linux developer
bcachefs for years and has never lost any Linus, and a codebase that I own and to feel that their contributions were
data using it. know like the back of my hand that’s better and more carefully written than
“However I am going to be blunt: as stuffed with assertions. And, the other people’s and deserving of special
someone who designs and builds changes in question are algorithmically treatment. Part of Linus’s main discov-
Linux-based storage servers (well, I fairly simple and things that I have ex- ery of the principles of open source de-
used to) as part of their job I would cellent test coverage for. These are all velopment was to encourage people in
never, ever consider using bcachefs pro- factors that let me say, with confidence, their contributions. In the spirit of fun,
fessionally as it is now and the way it that there really aren’t any bugs in this I will say, if Linus turned developers
appears to be developed currently. It is this pull request. away simply because they were arro-
simply too much changed too fast with- “Look, there will always be a natural gant, he might have run out of contrib-
out any separation between what is tension between ‘strict rules and utors a long time ago. Q Q Q
QQQ
Ghost Coder
Artificial intelligence is increasingly supporting programmers in their daily
work. How effective are these tools? What are the dangers? And how can
you benefit from AI-assisted development today? By Tim Schürmann
D
evelopers have been using artificial intelligence for suggestions while the developer is typing. The additions will
decades. Even text editors such as Kate offer syntax complete lines started by developers and typically even finish
highlighting and auto-completion. Under the hood, off whole functions. The snippets that GitHub Copilot [5]
these tools are based on pre-
defined rules. If the editor encounters
the for character string, for example, it
highlights the string in green. Modern AI
assistants are far smarter, opening up
completely new possibilities for
developers.
For instance, what happens if you
want to convert your existing program
code from C to the more modern Rust?
No problem for CodeConvert [1]. The
cloud service can translate source code
between many programming languages
(Figure 1). In addition to well-known
representatives such as Go and Python,
you can also translate code from more
exotic languages such as Ocaml, Cobol,
and Tcl. Other translators, such as Re-
fraction [2], Codeium [3], and Figstack
[4] also help you beam your code to dif-
ferent languages, but these tools can do
far more.
The translator tools use plugins to
connect to the development environ- Figure 1: In CodeConvert, you download the existing source code on
ment, monitor the programmer’s work in the left, press a button, and receive the counterpart in Rust or another
the background, and then make coding language on the right.
Hallucinations
If you believe the many videos and mar-
keting texts on the Internet, AI wizards
effortlessly pull complex code snippets
in countless languages out of their hats.
The providers try to outdo each other in
their claims. Refraction claims to support
56 programming languages, and Code-
ium supports more than 70. It all sounds
too good to be true. And, as anyone who
has tried out the tools in a larger project
will be aware, it often is.
The AI wizards are capable of writing
simple functions such as Bubblesort or
the Euclidean algorithm from Figure 3
quite reliably. They will even provide
new solutions or implement ideas that
Figure 2: In the Codeium Playground on the Codeium website, you can programmers might not have thought
test the AI wizard without any obligation, but only on a handful of of. However, if you need more complex
languages. code, you will often only see unusable
suggestions, some of which are not
outputs also stick to the coding conventions of the rest of the even recognizable as code (Figure 4).
document. AI coding thus goes far beyond conventional rule- Problems of this kind are due to the way the AI tools work:
based autocompletion. The source code of neural networks is generated in the back-
In order to autonomously complete a function, the wiz- ground, usually in the form of Large Language Models (LLM).
ards use the existing or surrounding code as a reference The programming wizards therefore use the same technology
point. Tabnine [6] is based on both the signature of a func- that powers ChatGPT. Unlike ChatGPT, however, the neural
tion and on a comment above it. Programmers can use hint networks are not simply trained with everyday knowledge from
lines to steer the AI to the right results. Keep in mind that Wikipedia but with existing source code. Tabnine and some of
many providers don’t bother describing the working meth- its competitors also offer to customize the resulting models for
ods of their AI tools. In the case of Codeium (Figure 2), for their customers. To do this, they train their models with the
example, it is unclear which lines the wizard takes into ac- private source code of the customer.
count when it generates code. In all cases, the neural networks will always suggest the kind
Most AI tools don’t just rewrite source code; you can also ex- of source code that they believe is most likely to match the ex-
plicitly ask them to solve a programming problem. You need to isting code. But when faced with complex code, the AI wizards
describe the task for the AI with a short sentence to immediately tend to go haywire. The resulting suggestions sometimes con-
see the matching code. For example, the AI wizards provide the sist of confusing instructions or are no longer fit for the pur-
complete code for sor algorithms or make suggestions relating to pose, although the code might require closer inspection to dis-
classes. Some tools, such as Refraction, can also derive a regular cover these issues (Figure 5).
Worse still: The generated source code can contain errors
and security vulnerabilities, for example, if the AI recom-
mends the use of an outdated API. The self-confidence that
Figure 3: Codeium completing the function for calcu- Figure 4: In other cases, there are either no sugges-
lating the greatest common divisor. tions or meaningless ones.
Legal Pitfalls
Another problem with the training data is
that AI users can never be sure whether
the source code generated on demand
Figure 5: Refraction generated code: Note that Refraction’s own code violates licenses, copyrights, or even pat-
audit feature immediately criticizes several items. ents. This problem is exacerbated if the
AI simply copies code snippets from the
the wizards appear to have tempts many developers to adopt training data and passes them off as its own. According to
the code without checking it carefully. In a blog post [7], GitHub, this happens with Copilot, especially if there isn’t very
developer Marcio Frayze shows how quickly bugs can slip much code in the programmer’s editor, or if the AI is asked for
through. very common solutions, such as a bubblesort algorithm. Source
code also often contains personal data, such as the email ad-
Exam Board dresses of the developers involved. Basically, this information
GitHub Copilot tries to mitigate these problems with filters. can also be found in the AI’s memory.
The filters scan the generated code snippet for common prob- GitHub tries to filter the output of email addresses, but you
lematic patterns. According to GitHub, potential problems in- can’t rule out the risk of some slipping through. And there is
clude SQL injections and hard-coded credentials. If Copilot de- duplicate detection to help prevent code copying. The GitHub
tects a problem, it blocks the suggestion or at least notifies the AI searches for the code snippet it has generated in all public
developer of the problem. Having said this, the AI wizard does GitHub repos. If it finds what it is looking for, it either blocks
not deploy any additional security measures. GitHub then rec- its proposal or reports the location and license. Developers can
ommends its other tools, such as GitHub
Advanced Security.
Programmers should always check the
auto-generated source code themselves.
GitHub Copilot and CodeConvert even
explicitly point this out in the small print
and in their FAQs. A second look is defi-
nitely recommended if a feature is still
tagged as beta or even experimental,
such as the Codeium Command function
in Codeium, which generates code that
matches a natural language description.
The quality of the suggestions largely
depends on the wizard’s knowledge base
and therefore on the training data. But
where the data comes from remains a
mystery throughout. It is only rarely that
providers cite a source. The notable ex-
ceptions include Tabnine and GitHub.
Both AIs learn from the source code in Figure 6: The AIs generate documentation relatively accurately. In this
publicly accessible repositories, including example, Codeium has written a correct comment for the task of
those on GitHub. However, there is computing the greatest common divisor.
then decide for themselves whether the suggested code and comment with a short, appropriate, natural-language descrip-
license are suitable for their project. tion (Figure 6). Like many other candidates, the AI developed
Despite this, some worries remain when you use Copilot. by JetBrains [9] for its IDEs also automatically writes commit
Duplicate detection only works if the code snippet exists in a texts. Although all the AI-generated texts still require a little re-
public GitHub repository, is at least 150 characters in length, work, as many developers confirm, the generated comments
and the developer is working with Visual Studio Code. In the substantially speed up the documentation work.
small print, GitHub points out that you must always check for You can also ask AI wizards to explain existing code to you
yourself whether Copilot’s proposals infringe on the rights of (Figure 7). In this way, you can quickly find out what the func-
other parties. In the case of active duplicate detection, GitHub tion (written by a former member of staff who long since left
at least promises support for Copilot users who are accused of the company) actually does. You can even ask Codeium, Tab-
copyright infringement. GitHub does not specify how far this nine, GitHub Copilot, and others questions about the source
help extends.
Even given a check like this, there is
always the question of the license under
which the generated code proposal is
registered. GitHub itself explicitly
makes no copyright claims to the code
generated by Copilot; other providers
are tacit on the subject. This and all the
other problems do not exactly speak in
favor of using AI wizards. On the up-
side, the wizards are still useful for
some specific tasks.
Documentation
Many developers see the documentation
of their source code as a pesky chore.
But this is a task that the AI wizards
carry out with an astonishing accuracy.
All programmers have to do is ask Code-
ium, Refraction, and the like to explain a
function and the AI will provide a Figure 8: Codeium provides details of the Fmt package included in Go.
code – for example, how one function uses another or what strings and numbers into variables and adds missing types.
patterns a cryptic regular expression covers. Figstack also Once again, the quality of the results depends to a huge extent
determines the runtime of the source code in O notation. on the complexity of the source code.
These tools can also help newcomers master a new language
(Figure 8). You can tell the AI wizards to show you examples Payment Plans
and ask questions about the existing code. Some AIs offer Most smart programming aids are only available as commercial
special assistance: Refraction will create an introduction to an cloud services, which the plugins for the development environ-
arbitrary programming topic on request, whereas JetBrains AI ments then consult. Alternatively, you can talk to the AI directly
guides you through the range of functions in the in-house IDEs. in the browser, but this means that you have to constantly copy
However, the texts of the AI tools sometimes sound very much the source code back and forth. Tabnine is one of the few pro-
like boring reference manuals, which is why many developers viders that lets you host its models on-premises yourself.
prefer to switch to ChatGPT for this task. Any free offers available are either time-limited or severely re-
stricted in terms of their feature set. Fees also vary considerably
Testing, Testing, 1, 2, 1, 2 among the services. Professional developers will pay at least
The AI wizards also offer useful support for testing. More specif- US$80 per year with Refraction, whereas GitHub Copilot charges
ically, they can automatically generate test cases or unit tests at US$19 per user and month. Special conditions are often available
the push of a button. The AI developed by JetBrains for its IDE for students, teachers, and developers of open source projects.
is based on both the source code and the documentation. Refrac- Looking for open source programming wizards is like finding
tion, in turn, automatically inserts debug texts into the code, a needle in a haystack, and they are also far more complex to
such as “All elements processed.” The AI derives the texts from set up. As with Tabby [10] and FauxPilot [11], you typically
the names of functions, variables, and other elements, which is need to launch a server in a Docker container. Well-known
why they often require some rework. Some AIs detect typical or open source models often operate in the background. Tabby
potential programming errors and alert you to them. These er- uses Code Llama, StarCoder, or CodeGen, for example.
rors can even happen while you are typing. Refraction even ex- Some AI wizards let you query with an API – via OpenAPI in
plains how the error occurred and how to remedy it. But none of the case of Tabby, for example. If you do not want to use Curl to
the AI assistants can guarantee completely error-free code. access these interfaces, you will need a matching client or a plu-
When things have to be done quickly, spaghetti code with gin for your own IDE. Fortunately, the Tabby project itself pro-
variables whose names consist of just one letter is still com- vides some plugins. In the case of FauxPilot, you either have to
monplace. Some AI tools are capable of unraveling this mess of resort to plugins from third-party developers or use tricks to per-
code and formatting it in compliance with a style guide. In ad- suade the official Visual Studio code plugin for the GitHub Copi-
dition to optimized code, Refraction offers natural language im- lot to cooperate (Figure 10). As an alternative to Tabby and Faux-
provement tips. For example, the AI complains about a lack of Pilot, you can install the Ollama framework [12] directly and use
input checking and meaningless variable names. Refraction, it to run an open source model such as Code Llama locally. If
Codeium, and others can automatically refactor the code (Fig- you decide to take this extremely bumpy path, you will find a
ure 9). Refraction also automatically converts hard-coded usable Visual Studio code plug-in in the form of Privy [13].
Figure 9: Refraction refactoring older Rust code while adapting it to current Rust versions at the same time.
Conclusions
Automatically generated tests and ref-
erences to best practices – according to
a survey of Go developers – is what
many programmers want from an AI
wizard [15]. And, at least with most
Figure 10: Some tools, such as GitHub Copilot, not only offer IDE commercial services, these wishes are
plugins but also support queries via a command-line tool. likely to come true. But no AI is cur-
rently able to implement complex code
Data Protection automatically. In practice, the wizards do their jobs primar-
In order to generate high-quality source code for different ily as enhanced auto-completers, documentation aids, and
languages, a wizard requires a large neural network and unit test generators. In these areas, the tools take tedious
huge amounts of training data. The required computing routine work off the developer’s plate, although you still
power and financial resources are primarily the domain of need to double-check the results. Q Q Q
large corporations such as Google, Amazon, and Microsoft,
as well as players like OpenAI. Smaller providers of pro- Info
gramming tools, such as the former pioneer Kite [14], are [1] CodeConvert: https://www.codeconvert.ai
falling by the wayside or are increasingly forced to rely on [2] Refraction: https://refraction.dev/
preparatory services by the global players. Refraction from
[3] Codeium: https://codeium.com/
Portugal, for example, uses customized models from
OpenAI. [4] Figstack: https://www.figstack.com/
This reliance on background services leads to a data protec- [5] GitHub Copilot: https://github.com/features/copilot
tion problem. In order to provide immediate suggestions, the [6] Tabnine: https://www.tabnine.com/
AI monitors the developer’s work and sends some of the [7] “What it was like to spend a month using GitHub Copilot and
source code to the cloud for evaluation. If you let CodeConvert why I plan to not use it (next month)”: https://dev.to/
translate all of your source code, for example, this means you marciofrayze/what-it-was-like-to-spend-a-month-using-
have sent the internals of your entire program to a company in github-copilot-and-why-i-plan-to-not-use-it-next-month-3ao5
India. In most cases, the providers also receive further informa- [8] “GitHub Copilot – what’s your experience been like? Worth
tion. GitHub Copilot collects various metrics such as the errors it?”: https://www.reddit.com/r/webdev/comments/11hmsqp/
reported by the development environment and the features github_copilot_whats_your_experience_been_like/
enabled in it. [9] JetBrains AI: https://www.jetbrains.com/ai/
What happens to the data in the cloud is up to the provider. [10] Tabby: https://tabby.tabbyml.com/
In particular, the source code and therefore important internal
[11] FauxPilot: https://github.com/fauxpilot/fauxpilot
enterprise data could be incorporated into the AI as training
[12] Ollama: https://ollama.com/
material. As a result, the wizards would then offer up your
company’s knowledge to other users. In the worst case, code [13] Privy: https://getprivy.dev/
fragments could even appear there. Manufacturers deal with [14] Kite: https://www.kite.com/blog/product/
this problem in different ways, and the pertinent details are kite-is-saying-farewell/
often hidden in the small print. GitHub Copilot, for example, [15] Survey of AI assistants: https://go.dev/blog/survey2023h2/
only guarantees for the business plan that the source code
sent to the cloud will not be used as training data. GitHub also Author
reserves the right to allow employees working on the Copilot Tim Schürmann is a freelance computer scientist and author.
project to view the requests. These include employees of Besides books, Tim has published various articles in magazines
Microsoft and OpenAI. and on websites.
ArcoLinux
ArcoLinux, an Arch derivative, offers easier installs while well as explanations of the different fla-
vors and derivatives of ArcoLinux, but
educating users about Arch Linux along the way. By Bruce Byfield the most interesting menu item is the
T
suggested learning path [3] shown in
oday, Arch Linux is in the same ArcoLinux’s emphasis on education Figure 1. The learning path begins with
state as Debian around the turn of is obvious from the choice of a .info warnings like “You will break your sys-
the millennium – popular for its domain name. The distribution boasts tem […] This is normal. 15 minutes later
technical excellence, but with a more than 4,000 videos on YouTube [2] you are back on a newly installed OS.”
reputation for being difficult to install. and proclaims in all caps on its site: ArcoLinux suggests that users begin with
Even with detailed installation documenta- “You ask a question that concerns a mostly automatic install that provides
tion and the minimal archinstall script, everyone we make a video.” an Xfce desktop on which they can learn
the reputation remains. As a result, just Moreover, the project’s home site in- curated apps, system configuration and
as Debian spun off rivals like Ubuntu and cludes a Start Here top-level menu. The maintenance, page management, key-
MEPIS that feature easy installs, so Arch Start Here menu includes the usual links board shortcuts and aliases, and become
has spun off distributions like Endeav- to review, news, and testimonials, as comfortable using the terminal. Users
ourOS and Manjaro. Among Arch Linux’s
derivatives, ArcoLinux is unique [1]. As
much an open university as a distribution,
ArcoLinux takes its inspiration from Arch
Linux’s extensive documentation as well
as its technology and organization. In the
process, ArcoLinux offers beginners and
veterans alike the experience of installing
an Arch-like desktop version.
Lead Image © maxkrasnov, 123RF.com
Author
Bruce Byfield is a computer journalist and
a freelance writer and editor specializing
in free and open source software. In
addition to his writing projects, he also
teaches live and e-learning courses. In his
spare time, Bruce writes about Northwest
Coast art (http://brucebyfield.wordpress.
com). He is also co-founder of Prentice
Pieces, a blog about writing and fantasy Figure 1: Phase 1 of ArcoLinux’s learning path is designed to systemati-
at https://prenticepieces.com/. cally to turn novices into experts.
Figure 2: The introductory installation stages include Figure 3: In the advanced installation, ArcoLinux
useful preinstall links. leaves the choice of apps to the user. Shown here is
the extensive list of desktops and window managers
can then move on to an advanced instal- users will only in- available during installation.
lation and other desktops, saving tiled stall a few times
desktops for last. From there, they can at most. However, ArcoLinux’s installa- ArcoLinux uses the Calamares in-
learn to create their own installation tion process warrants more detail than staller. What distinguishes ArcoLinux’s
images, how to install Arch Linux itself, usual because it is shaped by the goal of version (Figure 2) is the addition of the
and, finally, how to create their own educating users. Some users may want Advanced Installation option. The intro-
Arch Linux derivative distribution. Read- to begin with Home | Info to learn about ductory stages of the install emphasize
ing the summary of the eight phases pro- burning a .iso to a USB drive or a virtual education and ease of use, but the over-
vides a clear picture of what separates a machine. Download images are available all impression is of a graphical version of
newcomer from a knowledgeable Linux from the Download menu, where they an Arch Linux install – something that
user. The learning path contains obvious are all briefly described in terms of de- almost seems a contradiction in terms –
biases, such as the need to know the fault applications and services, as well and a tool that rivals the Debian installer
command line or the assumption that as ease of use. Some are characterized for comprehensiveness and user control.
tiled desktops are an advanced choice, by the type of kernel, others by the desk- It starts with a choice of graphics that in-
but probably few long-time Linux users top. Each of the downloads – Arconet, cludes pure open source or NVIDIA. It
would disagree with these biases. The ArcoPro, and ArcoPlasma – also has its then moves on to a choice of options to
overall effect is a summary for beginners own video that users can watch before update download mirrors, to partition
that, as far as I know, is unmatched any they install. with GParted, and to set screen
place else.
In following the learning path, users
can refer to other menu items. Although
the links are often obscurely named, the
Home menu contains detailed guidelines
for each phase, as well as a link to the
user forum. Users designing their own
installation images may also want to
refer to Home | ArcoLinux | Applications
for information about widgets, termi-
nals, and similar images. Unfortunately,
though, many of the items in the General
menu about configuration and hardware
are still placeholders, so following the
learning path may also require addi-
tional web searches. No doubt Arco-
Linux will get to these topics in time.
Installing ArcoLinux
When reviewing most distributions, I
generally try to keep the description of
the installation minimal. After all, most Figure 4: The default desktop for the ArcoPlasma flavor of ArcoLinux.
Do you want to be alerted when a product is back in stock on your favorite online store? Do you
want to know when a website without an RSS feed gets an update? With changedetection.io,
you can stay up-to-date on website changes. By Koen Vervloesem
I
f you want to stay updated on
news from various websites, Really
Simple Syndication (RSS) [1] is a
great solution. Many websites offer
their news in an RSS feed, which is an
XML file with a specific format. You can
subscribe to these feeds and read the
content in RSS feed readers, which can
be graphical, command-line, or web-
based clients.
However, not all websites provide an
RSS feed, and RSS usage seems to have
diminished somewhat in recent years.
Moreover, not all websites offer their
content in the form of articles. Still, you
may want to know about changes on
these websites, such as the price of your
favorite product on an online store or a
new page in the table of contents of an
online document. Are you then doomed
to regularly visit all those websites
you’re interested in?
Lead Image © rendeeplumia, 123RF.com
under the Apache 2.0 license. The devel- $ sudo usermod -aG docker $USER two web pages as examples: the chan-
oper simply offers this solution as a sub- gelog of its own releases, and the
scription to fund development. Log out and log in again to apply the Hacker News homepage. Each of these
group membership. Next, create a data “change detection watches” gets its
Installing changedetection.io directory for the container: own row in a table. For each page, this
Changedetection.io is a Python program, table shows the last time it was checked
which you can install using Python’s $ mkdir changedetection as well as the last time it changed. If the
package manager pip. However, because page has a change that you haven’t
you probably want to run this continu- Then create a docker-compose.yml file viewed yet, the entire row is shown in
ously as a service, it makes sense to run with the content from Listing 1. bold. Clicking on the Diff button then
it in a Docker container. On Ubuntu Of course, you need to modify the shows the changes, with new lines in
24.04 LTS, install Docker and Docker path in the volume to match your user’s green and deleted lines in red. A click
Compose with home directory. Now, start changedetec- on Reset queues a new check of the
tion.io with: page if you don’t want to wait for the
$ sudo apt install docker.io docker-U next scheduled check. By default, pages
compose-v2 $ docker compose up -d are checked every three hours.
Each page can have one or more tags,
Then add your user to the docker group: If you run this on your desktop or such as Tech news or another general
laptop, simply category. These tags are also shown next
Listing 1: changedetection.io Docker Compose File visit http:// to the page in the change detection
01 version: '3.2'
localhost:5000 in watch table, and there are also tabs for
your web browser each tag. If you click on a tag, the table
02 services:
to access the user only shows pages with that tag, provid-
03 changedetection:
interface (Fig- ing a clearer overview if you have many
04 image: ghcr.io/dgtlmoon/changedetection.io
ure 2). If you run pages added to your watch. At the bot-
05 container_name: changedetection this on a server, tom right of the table, you can always
06 hostname: changedetection just replace local- mark all pages of the current tag as
07 volumes: host with its IP viewed, recheck them all, or get an RSS
08 - /home/koan/changedetection:/datastore address. feed with changes of these pages for you
09 ports:
to add to your RSS feed reader.
10 - 5000:5000
The Basics Each page also has two grayed-out
Changedetection. icons at the start of its row. Clicking on
11 restart: unless-stopped
io starts watching the first one pauses the checks for this
page, and clicking on the second one than a 100 popular services, including Don’t forget to click on Save at the bot-
stops notifying you of changes, but Telegram, Discord, Slack, Home Assis- tom to save your notification settings.
keeps checking for them. A click on the tant, Kodi, Pushbullet, and email. For For now, you can ignore the other tabs of
Edit button opens the settings for the each of these services, Apprise defines changedetection.io’s settings.
page’s change detection watch. a URL. I’ll use sending emails with
Mailjet [5] as an example (for more ex- Adding a New Change
Basic Settings amples, see the Apprise wiki [6]). Detection Watch
Before adding pages, I’ll first cover some Enter one or more Apprise URLs in If you want to monitor a specific web
of changedetection.io’s basic settings. changedetection.io’s Notification URL page for changes, you can simply add
After clicking on Settings at the top right, List. For Mailjet, this looks like the URL in the text box at the top,
the General tab allows you to set the under Add a new change detection
time between checks (the default is three mailtos://username:[email protected] watch. Optionally, add one or more tags
hours), as well as other general settings. mailjet.com?from=Change%20DetectionU (separated by a comma), and then click
This is where you can set a password on <[email protected]>&to=U on Watch to add the watch with the de-
changedetection.io. Click on Save at the [email protected]&mode=ssl fault settings or Edit | Watch to edit the
bottom if you change any of the settings. watch’s settings before adding it.
In the Notifications tab (Figure 3), you This defines the notification as secure By default, changedetection.io
define how changedetection.io sends SMTP, with a username and password watches for web page text/HTML, JSON,
you notifications when it detects a page for login and a from and to email ad- and PDF changes. However, if you select
change. You can leave this field blank if dress in SSL mode. Re-stock & Price detection for single prod-
you’re content with regularly checking the If you then click on Send test notifica- uct pages, the program looks for signs of
watch list manually or if you monitor the tion, you should receive a notification a price or terms such as “in stock” or
changes in your RSS feed reader. But if you on all services you set up. If not, click “out of stock,” which lets you watch for
want faster notifications, set this up here. on Notification debug logs and try to changes in prices or stock status. Note
Changedetection.io uses Apprise [4] find out what went wrong. You can also that this only works if the page covers
for notifications. Apprise is a library that change the title and body of the notifica- one product.
supports sending notifications to more tions, but the defaults are often fine. There’s also a Chrome extension [7]
that works together with your change-
detection.io instance. Just add it to
Chrome, open your changedetection.io’s
Settings and go to the API tab. Then
open the extension from the toolbar and
click on Sync API Access. The extension
then automatically configures itself to
talk to your changedetection.io instance.
On any page, you can now click on the
extension icon in the toolbar, select
whether you want to detect normal
changes or stock and price changes, op-
tionally add one or more tags, and click
on Watch this website to add a change
detection watch (Figure 4).
Figure 4: With changedetection.io’s Chrome extension, monitoring page changes becomes even easier.
page changedetection.io monitors for watching has a footer showing how footer. So I added the XPath filter //main
changes. The Visual Filter Selector is ad- many “bad” access attempts it has to the CSS/JSONPath/JQ/XPath Filters
vanced functionality that I’ll explain blocked. Naturally, this triggers change text box on this tab. Don’t forget to save
later, and Filters & Triggers allows you to detections I’m not interested in. When your changes.
remove HTML elements or select only examining the web page’s HTML code, I For stock and price detection, the Re-
specific HMTL elements from the page. noticed that the main element contains stock & Price Detection tab allows you to
For example, one of the web pages I’m all the information I need, without the adjust the watch’s behavior. For example,
you can specify whether you want to
know about any availability changes or
only when an out-of-stock product is back
in stock. You can also enable and disable
price monitoring, and you can even trigger
notifications when the price changes
below or above a set value (Figure 5).
For both types of change detection
watches, the Notifications tab allows you
to modify the behavior from using the
general notification settings to some-
thing custom for this watch. For in-
stance, you can disable notifications for
this watch or add another Apprise URL
for a custom notification. The Stats tab
simply shows some statistics of the
watch and allows you to download the
latest HTML version that changedetec-
tion.io has downloaded from the page to
debug any issues.
Using a Chromium/
JavaScript Server
Figure 5: Trigger a change when the price drops below or rises above a By default, changedetection.io down-
specific value. loads the watched pages as plain HTML
08 - /home/koan/changedetection:/datastore 21 environment:
09 ports:
22 - SCREEN_WIDTH=1920
10 - 5000:5000
23 - SCREEN_HEIGHT=1024
11 environment:
24 - SCREEN_DEPTH=16
12 - PLAYWRIGHT_DRIVER_URL=ws://playwright-chrome:3000
files using an HTTP client. This works To configure this, update your $ docker compose up -d
for many web pages and is fast. How- docker-compose.yml file with the Docker
ever, as soon as a page uses JavaScript to Compose file shown in Listing 2. In principle, you could now change
render important parts of its content, This adds a second container run- changedetection.io’s fetch method to
this simple HTTP client won’t see the ning a Chromium web browser and Playwright Chromium/Javascript via
content. Fortunately, you can run a web lets changedetection.io’s container ‘ws://playwright-chrome:3000’ in its set-
browser in a Docker container and let wait until this container is started. tings, but the default fetch method is
changedetection.io use it to fetch the After these changes, restart Docker much more efficient. It’s recommended
watched pages. Compose with: to only change the fetch method for indi-
vidual watches where the default
method doesn’t work.
You can make this change in the Re-
quest tab of the watch settings by chang-
ing the Fetch Method to Playwright Chro-
mium/Javascript via ‘ws://playwright-
chrome:3000’. Save your changes and
wait for the queued watch to be exe-
cuted. If all goes well, the change detec-
tion watch works now. However, some
websites (such as Amazon) detect that
you’re visiting them with a bot, so they
don’t show the desired content. You can
check this by clicking on Preview next to
the change detection watch. If you go to
the Screenshot tab, you’ll see what the
page looks like to the browser in the
container, and this often shows a CAPT-
CHA. There are solutions for this prob-
lem, such as Bright Data’s (paid) Scrap-
ing Browser [8], but that is beyond the
scope of this article.
web page, and when you hover over dif- between checks appropriately: You don’t expressions. Before you know it, you’ll
ferent parts of the page, you see a red want your account blocked because have this service constantly browsing
bounding box (Figure 6). Click on the changedetection.io logs in too the web for you, notifying you of any-
box to select the element you want to frequently. thing you need to know. Q Q Q
use for change detection. This automati-
cally fills in the corresponding filter in Conclusion Info
the Filters & Triggers tab. You can also Changedetection.io can be a great tool [1] RSS: https://www.rssboard.org/
select multiple elements. Click on Save for being notified of web page changes. rss-specification
to confirm the filter. Once you have it running for a few [2] changedetection.io:
Another advantage of using the Chro- websites without an RSS feed, you’ll https://changedetection.io
mium/JavaScript server can be found in likely add more and more change de-
[3] changedetection.io source code:
the Browser Steps tab. By clicking on the tection watches. The filters and trig-
https://github.com/dgtlmoon/
play button there, changedetection.io gers are quite powerful, and you can changedetection.io
creates a live connection to a web even ask changedetection.io to extract
[4] Apprise:
browser, and you can interact with the text from a page using regular
https://github.com/caronc/apprise
page from within this browser. You can
[5] Mailjet: https://www.mailjet.com/
then perform actions such as clicking on Author
a cookie accept box or logging into the Koen Vervloesem has been writing about [6] Apprise wiki: https://github.com/
website. After saving this, changedetec- Linux and open source, computer security, caronc/apprise/wiki
tion.io replays these steps every time be- privacy, programming, artificial intelli- [7] Chrome extension:
fore its change detection watch. You can gence, and the Internet of Things for more https://chromewebstore.google.com/
use this, especially in combination with than 20 years. He holds master’s degrees detail/changedetectionio-website/
the Visual Filter Selector, to get alerts in Computer Science Engineering and Phi- kefcfmgmlhmankjmnbijimhofdjekbop
about information shown only after log- losophy and is teaching Linux, Python, [8] Bright Data’s Scraping Browser:
ging in, such as new invoices or private and IoT classes. You can find more on his https://brightdata.com/products/
messages. Of course, adjust the time website at koen.vervloesem.eu. scraping-browser
IN-DEPTH
Linodas
Through
the Back
Door
Cybercriminals are increasingly discovering Linux and adapting malware previously designed for
Windows systems. We take you inside the Linux version of a famous Windows ransomware tool.
By Thomas Boele
S
ince the beginning of the year, South America. The toolkit for this This article provides technical analysis
security researchers from Check threat actor includes the DinodasRAT [1] of the Linux version (v11) of DinodasRAT,
Point Research (CPR) have been cross-platform backdoor, also known as aka Linodas. The Linux edition appears
investigating the activities of a XDealer, which was previously observed to be more sophisticated than the Win-
Chinese cyber espionage threat actor in attacks by the Chinese group known dows version and has a range of features
focused on Southeast Asia, Africa, and as LuoYu. specially tailored to Linux servers. In
Figure 1: Similarities in the function for identifying the operating system version between the Dinodas
example (left) and the open source code. © Check Point Software
addition, the version under investigation Two samples with different internal rc.local.service file exists and writes
introduces a separate bypass module to versions suggest that there were two dif- the code from Listing 1 to the file.
hide traces of malware in the system. ferent development teams or at least two It then creates the following symlink.
The execution of the system binary files backdoors in different stages of develop-
is modified by proxies. ment communicating with the same C2 /lib/systemd/system/rc.local.service U
server. The Linux and Windows versions --> /etc/systemd/system/
ilarities between SimpleRemote and an named ntfsys that pretend to be system [SELF_FILE_PATH] exit 0
older version of DinodasRAT include the or driver files in the context of the NTFS
use of the same Zlib library (version filesystem. Linodas then runs the chmod 777 com-
1.2.11) and some overlaps in the code As soon as the backdoor is executed, it mand to make the /etc/rc.local file ex-
(Figure 1). checks whether it has been launched for ecutable and evaluates whether the per-
The developers of DinodasRAT re- the first time by requesting two argu- sistence has been correctly written to
hashed parts of the source code and ments: the letter d and the process ID of the file. Finally, the malware changes
added some additional open source code the calling daemon. If it cannot find the the INI fields in the /lib/systemd/system/
from another repository. This code in- arguments, it calls the daemon function rc.local.service file (Listing 2).
cludes functions for handling INI files. and establishes its persistence on the
DinodasRAT uses encryption used in system. The backdoor then restarts itself. Listing 1: rc.local Activated via systemd
QQ Messenger. It retrieves the process ID and its exec [Unit]
self path and calls the system function
Description=/etc/rc.local Compatibility
Independent Code Base to run the [SELF_PATH] d [SELF_PID]
ConditionFilelsExecutable=/etc/rc.local
All examples of the cross-platform Dino- command.
After=network.target
dasRAT embed a string containing the
internal version of the backdoor. Some Persistence Methods [Service]
strings reflecting the development of the The persistence process is relatively ex- Type=forking
backdoor appear in Table 1. tensive and includes several Ubuntu ver- ExecStart/=etc/rc.local start
The earliest version for Linux was first sions and Red Hat distributions. The first TimeoutSec=0
spotted in the wild by security research- step is to determine the current operat-
RemainAfterExit=yes
ers in July 2021. Linodas has the same ing system version by reading the /proc/
logic as the Windows version, but it version and etc/lsb-release files and an-
adds a number of its own behaviors and alyzing the output. Then, based on the Listing 2: Changing INI Fields
specifically targets Linux servers. The data collected, persistence can be [Service]
latest Linodas version (v11) can also be achieved using one of the following
RemainAfterExit=no
observed in a Windows version, which methods.
[Install]
communicates with the same C2 server Method 1 (Ubuntu) – rc.local activated
WantedBy=multi-user.target
update.microsoft-setting[.]com (see via systemd: The malware first checks
Alias=rc-local.service
Table 2). whether the /lib/systemd/system/
Method 2 (Red Hat) – init.d script: Core Logic and used later on when the backdoor
The backdoor calls up the command, After the malware has executed correctly contacts C2 for the first time. The hard-
the output from which is analyzed by with two arguments, it moves on to the coded C2 address is parsed, stored in a
Chkconfig, and attempts to execute it. actual logic. First, it runs a series of global structure, and the malware reads
If the command is found and executed checks, including root privileges, the two more configuration fields, mode and
correctly, it adds it to the PATH environ- path/folder, and the process ID of the checkroot, from the para section. The
ment variable and continues with the calling daemon and saves them all in mode field specifies the transport proto-
actual persistence. The malware global variables. The backdoor then col to use: TCP or UDP. In contrast, the
checks whether the file /etc/init.d/ changes the timestamp of its file. checkroot field determines whether the
[SELF_FILE_NAME] exists and then writes backdoor should monitor logged-in
the code from Listing 3 to it. touch -d \"2010-09-08:*12:23:02\" U users. After the initial configuration, the
If the file has not been created, it [SELF_FILE_PATH] backdoor generates several threads that
writes the same data to the /etc/ch.sh are used for monitoring and cleaning
file and executes the following Now a configuration file based on the up. It then initiates the connection to
command: hard-coded string /etc/.netsc.conf is the C2 server.
read. The configuration files for all ex-
mv /etc/ch.sh /etc/init.d/U amples are usually hidden files. From Monitoring and
[SELF_FILE_NAME] the configuration file, the malware at- Cleaning Up
tempts to read the imei field under the The backdoor creates five threads that
The malware then executes the chmod 777 para section. The field stands for the are tasked with system monitoring,
command for the created file and checks bot ID generated for the infected com- downloading helper modules, and clean-
the persistence using the next call: puter. If it is missing in the configura- ing up old reverse shell connections.
tion file, a unique computer ID is gen- Thread #1 handles monitoring of the
chkconfig --list | grep U erated on the basis of computer param- logged-in user. If the mode field in the
[SELF_FILE_NAME] eters in five steps. configuration or the global variable for
The first step is to determine the com- mode is set to 1, this thread monitors
If the result does not contain 6:, the fol- puter’s MAC address. The malware runs logged-in users with the who command.
lowing two commands are used: the ifconfig or ip command and extracts It analyzes the output and closes the C2
the MAC address from the output; this de- connection if the registered IP is not a
chkconfig --add [SELF_FLE_NAME] U pends on the distribution. The malware local IP or the C2 IP.
chkconfig zentao [SELF_FLE_NAME] then calls the dmidecode command to ob- Thread #2 is responsible for monitor-
tain the system’s SMIBIOS. After it has ing the C2 connection status. Each
Method 3 (Red Hat) – rc.local: Persis- combined the MAC address and the out- time a valid request is made to the C2,
tence takes place via the file /etc/rc.d/ put of dmidecode, it executes the md5sum the time field in the global C2 connec-
rc.local. If the file exists, the backdoor command. Finally, in the fourth and fifth tion structure is updated. If half an
checks whether its self path exists in the steps, the backdoor generates a random hour has passed since the last request
content – if not, it adds itself to the file number and a timestamp based on the to the C2 server, the thread closes the
with the \n[SELF_PATH]\n string. current time. All of the fields and an ex- connection to C2.
ample are shown Thread #3 downloads and sets up the
Listing 3: Modify /etc/init.d/[SELF_FILE_NAME] in Listing 4. After filter module. The thread first uses a
#!/bin/sh
it is generated, the variable to check whether the module
bot ID is saved in has already been downloaded. If this is
### BEGIN INIT INFO
the configuration not the case, the thread again carries
# Provides: [SELF_FILE_NAME]
file and the config- out a few steps. It first checks whether
# Required Start: $local_fs $network uration file time- the file [SELF_PATH].so6 exists and com-
# Required Stop: $local_fs stamp is also putes an Md5 hash of its content. It
changed, as with then sends an encrypted request to C2,
# Default Start: 2 3 4 5
the executable file. in which it requests the Md5 hash of a
# Default Stop: 0 1 6
The backdoor module available on the C2 server and
# Short Description: [SELF_FILE_NAME] service then enumerates compares the received Md5 hash with
# Description: [SELF_FILE_NAME] service daemon the system to de- the existing one.
### END INIT INFO
termine the distri- If the hash is different, the thread
bution, the exact makes another request to C2 and saves
[SELF_FULL_ATH] restart
operating system the newly received file under the same
version, and the name. In the second-to-last step, it
Listing 4: Unique Computer ID system architec- reads the data from the /usr/lib/lib-
Linux_[TIMESTAMP]_[MD5SUM]_[RANDOM NUMBER]_V11
ture. All of these sysattr.so file; this was probably stored
values are stored at an earlier stage of the infection. This
Linux_20240310_11cb06d0bf454c3708a3658c2601ea16_40459_V11
in global variables file should contain a series of values
separated by pipes (|) and includes a match a local IPV4 or one of the C2s, be used when connecting to C2; the
series of instructions for executable its details are logged and sent to the C2 other specifies whether C2 communi-
files to be replaced. The thread now server. cation should be interrupted if there
searches the system for each file listed Thread #5 takes care of cleaning up are logged-in users. If one of these
in the statement file and saves it as old reverse shell sessions. First of all, the checks fails, the malware does not es-
[FILE_NAME].a. thread monitors reverse shell sessions. If tablish communication with C2. If the
Finally, the thread replaces the original a reverse shell session is found that has checks are successful, the backdoor
files with the newly obtained So6 filter not been active for almost an hour, the analyzes the C2 address and resolves a
module and makes it executable. All of session is removed. C2 domain to IPv4 if necessary.
these steps allow threat actors to put Next, the malware sets up a socket in
wrappers around specific executable C2 Communication TCP or UDP mode, depending on the
system files. Before C2 communication begins, two configuration, and attempts to establish
Thread #4 monitors and logs logged- global structures are checked: One a connection to the C2 server. If the con-
in users. If a user is logged on to the contains the configuration value that nection is successful, the malware starts
Linux machine and their IPv4 does not specifies whether TCP or UDP should a thread to parse C2 commands. After
this first connection to the C2 server has support this function. The filter module This step merges the error output with
been established and the C2 command (Figure 2), which was obtained by the standard output so that both can
thread has been created, the backdoor executing ntfsys (v11) from the C&C be manipulated or viewed together.
executes an infinite loop that is respon- server controlled by the actor, is stored While the module executes the sub-
sible for sending a heartbeat to the C2 as ntfsys.so6. routine, it reads parts of the output and
server. The heartbeat contains the fol- The module has the task of control- splits them line by line. Each line runs
lowing values, which are combined ling the execution of the binary files through a filter process in which the
and separated by \t: information about and monitoring their output (Figure 3). line that contains one of the values for
the distribution, the system architec- The module is started each time the ip or name from the configuration is ig-
ture, the string root, the constant value system attempts to use the replaced bi- nored. If the line passes through the
0xC, the UDP packet length 800, and a nary file, with or without parameters. filter, it is printed.
custom path. If the request to C2 has As soon as it is executed, the module The threat actors probably deploy
failed, the connection to C2 is re-estab- checks whether the configuration file this module as a rootkit to filter arbi-
lished; the heartbeat string is then gen- is in /usr/lib/libsysattr.a. This sepa- trary values such as IP, username, pro-
erated and sent again. rate configuration file is not down- cess name, or other artifacts from vari-
loaded together with the module. In- ous binaries in order to collect infor-
Supported C2 Commands stead, the threat actors drop it onto the mation provided by commands such as
Much like the Windows backdoor, the server using the Linodas reverse shell. who, netstat, ps, in order to hide Lino-
Linux backdoor also supports a wide The module loads the ip and name das from monitoring attempts.
range of functions. These functions are fields from the para section of the con-
all listed in Table 3. The table also figuration file. The module combines Conclusions
shows whether they are present in the all received parameters, separates them The Linux version of DinodasRAT ap-
Windows version of the backdoor. with spaces, and checks whether the pears in connection with Chinese APT
original binary file with the name threat actors and has been used repeat-
Filter Module [SELF_PATH].a exists. If not, it outputs edly since at least 2021. Although Lino-
In Linodas v11, thread #3 is responsible the bash shell and exits. das has numerous similarities with the
for downloading an additional module However, if the file exists, the mod- Windows version, the Linux malware
that replaces all specified binaries in the ule executes it with the received argu- points to a separate and independent
system. None of the previous versions ments and appends the string 2>&1. development branch. Linodas intro-
duces add-on modules with separate
configuration files and additional C2
commands that focus on setting up
and controlling reverse shells, collect-
ing user activity from logs, and manip-
ulating local file contents. Q Q Q
Info
[1] DinodasRAT:
Figure 2: File identifiers for the filter module when it first appeared in https://malpedia.caad.fkie.fraunhofer.
November 2023. de/details/win.dinodas_rat
[2] SimpleRemote: https://github.com/
microsoft/SimpleRemote
[3] Gh0st RAT: https://malpedia.caad.fkie.
fraunhofer.de/details/win.ghost_rat
Author
Thomas Boele is an experienced tech
expert and recognized speaker. He has
more than 20 years of experience creating
go-to-market strategies for global IT
companies and start-ups by developing
and building pre-sales organizations in
high-growth environments with results-
oriented, supportive work cultures. Before
joining Check Point Software as Regional
Director, Sales Engineering CER/DACH,
he worked for companies such as Cisco,
Figure 3: Diagram of the execution of a system binary wrapped by the 3Com, NetApp, Riverbed, HPE SimpliVity,
filter module, which changes its output in real time. © Check Point Software Cohesity, and Twilio.
A modern cd command
Smarter
Navigation
Zoxide, a modern version of cd, lets you navigate long directory paths with less typing.
By Bruce Byfield
I
n most shells, the main navigation Installation and felix and ranger, as outlined on the
utility is cd (change directory). Configuration GitHub page [1]. Usually, integration in-
Generally, cd is built into the shell, Zoxide is available in many distribu- volves the installation of a sub-project.
which is why it does not have its tions, as well as on multiple platforms For example, for Vim and neovim inte-
own man page like other commands. and in multiple package formats. How- gration, zoxide.vim must be added via
The lack of a man page is usually not ever, installing the package is just the one of several package managers, and it
noticed, because the bare cd is all that beginning. To be functional, zoxide re- is used by a half dozen Vim commands.
most users need. However, when direc- quires at least some configuration. Similarly, Emacs integration requires
tories have multiple levels, cd can re- To start, users need to add zoxide to zoxide.el and enables a dozen func-
quire tedious typing, especially when their shell. In Bash, the line tions, such as zoxide-cd and zox-
you have to travel up the directory struc- ide-open-with. Unfortunately, many
ture and down another branch. A mod- eval "$(zoxide init bash)" popular text editors, such as JOE, or
ern version of cd, zoxide, changes all file managers like Dolphin or Caja, are
that by using a database that, once set must be added to the end of ~/.bashrc. not yet supported.
up, requires the typing of only the last This line can be added manually, or with Zoxide’s behavior can also be set with
directory in the path. zoxide-init (more on this later). The environmental variables:
To get its results, zoxide relies on an project’s GitHub page gives instructions • _ZO_DATA_DIR: Specifies the directory in
algorithm based on how often a direc- for other common shells. In order for which the database is stored. The de-
tory is accessed. When first added to the zoxide to deal with directory name con- fault is $XDG_DATA_HOME or $HOME/.
database, a directory is given a score of flicts, the fuzzy searcher fzf must be in- local/share.
1. Each time it is accessed, its score rises stalled. Optionally, you can change the • _ZO_ECHO: When set to 1, z will display
Lead Image © alexandragl,, 123RF.com
by one. When a query is made, a direc- default command z with cmd NAME, even the matched directory before navigat-
tory adds 4 if accessed in the last hour replacing the cd command. Directories ing to it. With this variable, you do not
and 2 if accessed in the last day or last that are scored in searches can also be need to run pwd from the destination
week. The higher the value, the most set with --hook SETTING, with a choice of for its complete path.
likely a directory is to be the one sought. none, prompt, or pwd. • _ZO_EXCLUDE_DIRS: Excludes the speci-
When the database reaches the maxi- Still another option is to integrate zox- fied directories from the database.
mum number of entries, it reassigns ide with other applications such as /home is included by default. This fea-
the frequency of access and deletes any Emacs, Vim, and neovim, as well as sev- ture can be useful for privacy and
directory that falls below 1. eral lesser-known file managers such as security.
• _ZO_FZF_OPTS: Provides custom options one directory with z .. or into the previ- Except for zoxide-query, none of the sub-
to pass to fzf during interactive selec- ous directory with z -. commands return feedback.
tion. Useful options include case-sen- For many users, no further informa-
sitivity, alternative ways of weighting tion is needed. However, zoxide’s data- Alternative Navigation
directories in search results, and as- base can be edited by subcommands If zoxide does not suit you, there are
sorted display options. See man fzf for placed after the basic command: other cd replacements, including auto-
the list of options. • zoxide add PATHS: Adds a path with a jump, z.lua, and rupa/z. Many of these
• _ZO_MAXAGE: Limits the maximum ranking of 1, or adds 1 to the ranking alternatives are structured similarly to
number of entries in the database. of a directory already in the database. zoxide, using a database and assigning
The default is 10,000. After either, the last updated field of directories a score based on frequency
the entry is updated. Directories ex- of use. Some, such as zsf, can be com-
Using zoxide cluded by the _ZO_EXCLUDE_DIRS envi- bined with zoxide during configuration.
All this lengthy configuration results in ronmental variable cannot be added. Data from some can be transferred to
the basic use of Zoxide being simple. This subcommand is a quicker way to zoxide. Keep in mind that zoxide has
Type z PATH, and the final directory is add directories than letting zoxide the advantages of being simple to use
added to the database. The next time learn from your navigation. and easy to learn.
you need to navigate to that directory, • -zoxide import --from FORMAT: The for- True, new users might wish for a
you only need to type z DIRECTORY, no mat is autojump or z for fasd, z.lua, or zoxide installer to replace the compli-
matter how deep in the directory tree it zsh-z. cated configuration process. More ad-
is buried. For instance, if you type • -zoxide-init: Automatically initializes vanced users might wish for additional
a command shell to read it for use. features, such as associating a direc-
z /home/bb/creative This action can also be done manually tory with a particular application.
in a text editor. However, once set up, zoxide in its
next time you only need to type z cre- • -zoxide query KEYWORDS OPTIONS: current form is a substitute for cd that
ative. Once zoxide is set up, you can Searches the database for keywords. is only slightly more complicated.
quickly add your most-used directories Options for results are --all and Users might want to make zoxide an
to the database and simplify your fu- --exclude PATH. With fzf installed, alias of cd by adding alias z='cd' to
ture navigation. When paths are simi- --interactive (-i) is enabled. With their shell configuration file. With zox-
lar, you can use zi as the basic com- --list (-l), all results are listed, not ide, users will save thousands of key-
mand or press Space+Tab to choose just the most used, while --score (-s) strokes, an improvement that is both
from a list (Figure 1). lists rankings, which can be manipu- efficient and ergonomic. Q Q Q
As the database is populated, zoxide lated with zoxide-add.
will choose the highest ranked directory • -zoxide remove PATHS: Deletes directo- Info
by default. You can change this behavior ries from the database. To permanently [1] zoxide:
by searching for multiple directories in remove a directory from the database, https://github.com/ajeetdsouza/zoxide
the path, or by specifying a subdirectory specify it in the _ZO_EXCLUDE_DIRS
with /. As in cd, you can also move up environment variable. Author
Bruce Byfield is a computer journalist and
a freelance writer and editor specializing
in free and open source software. In
addition to his writing projects, he also
teaches live and e-learning courses. In his
spare time, Bruce writes about Northwest
Coast art (http://brucebyfield.wordpress.
com). He is also cofounder of Prentice
Figure 1: When directories contain similar names, zoxide provides a list Pieces, a blog about writing and fantasy at
of alternatives to select from. https://prenticepieces.com/.
QQQ
Monkey Business
Even small changes in a web page can improve the browsing experience. Your preferred web
browser provides all the tools you need to inject JavaScript to adapt the page. You just need a
browser with its debugging tools, some knowledge of scripting, and the browser extension
Tampermonkey. By Reinhard E. Voglmaier
T
he browser has become a very automation tools or similar functional- the document itself. You can consider
important component for inter- ities, and this construct as similar to the chicken-
acting with the Internet. In recent • providing easy access to AI-based and-egg question: The document con-
years, browsers have evolved tools. tains the script and the script can mod-
from being just a tool for interacting This flexibility and power push the ify the document, including the script it-
with static HTML to a comprehensive browser far beyond its original role of self. The technology that allows this is
part of the infrastructure. The modern simply rendering HTML. the DOM (Document Object Model) [1]
browser is a kind of operating system [2]. When a web page is loaded, the
within the operating system, with a com- Before I Start … browser constructs a DOM tree, which is
plete SDK for JavaScript, HTML, and This article is intended for educational a hierarchical representation of the doc-
CSS, along with features such as a visual purposes only. My goal is to show you ument’s content. This tree structure al-
debugger, a code inspector, options for the power of the described technologies. lows for efficient selection, addition, re-
network and performance monitoring, All information you will find here is al- moval, and modification of elements on
and much more. One interesting features ready available on the Internet – links the web page. The DOM is not tied to
is that you can modify pages already are provided at the end of this article. As any programming language; however,
loaded into the browser with your own with many tools used for programming, JavaScript is commonly used to interact
scripts. The ability to customize web these tools can also be used for illegal with the DOM.
Photo by Jamie Haughton on Unsplash
pages is useful for: activities. If you decide to experiment, it Style sheets (CSS) also are part of the
• quick bug fixes for intranet is up to you to obey all applicable laws DOM. A style sheet describes how the doc-
applications, and treat any websites in a way that is ument will be displayed in the browser
• fixing annoying behaviors of websites compliant with their intended use. (the font, the colors, and so forth). The
or web applications, most interesting feature of the browser is
• implementing security features for Welcome to the DOM that the user can inject code into the DOM.
users in the enterprise, One very exciting feature of today’s web This code can interact with the HTML and
• adding convenient new features to is the connection between the HTML CSS part of the document. This feature
publicly available websites, such as document and the scripts contained in opens a world of possibilities.
Listing 1: manifest.json Listing 2: main.js executed when the user clicks the
{ const btn =
Clickme button. Look online if you’re in-
document.createElement('button'); terested in learning more about creating
"manifest_version":2,
btn.textContent = "Clickme"; extensions [3] [4].
"version":"1.0",
btn.onclick = function() {
"name":"Hello World",
alert("Hello World!");
Permanence
"content_scripts":[ So far, the plugin you created is only tem-
}
{ porary. When you restart the browser,
alert("JavaScript loaded!");
"matches":["*://*.perl.org/*"], you have to load it again. With the help
document.body.appendChild(btn);
"js":["main.js"] of the Node.js framework and a function
}
called web-ext, you can create a perma-
is called main.js (Listing 2). The script is nent extension. Now that you understand
]
located in the same directory as the the basic process, I’ll show you an easier
}
manifest file. way to achieve the same result: using an
The script doesn’t do much, but it illus- extension such as Tampermonkey [5].
Extending the Browser trates very well what is possible. You add
Integrating code into the DOM is easy. a button to all pages matching the do- How Tampermonkey Helps
Consider the classic “Hello World” ex- main perl.org. You also define a new Ja- Tampermonkey lets you permanently
ample to demonstrate this process. You vaScript function to be executed when load a user-defined extension into your
need one file called manifest.json (List- the button is pressed. For simplicity, this browser. You can use Tampermonkey to
ing 1) and at least one program file. function only executes the alert function. inject JavaScript code into the DOM to
manifest.json outlines several details, Now you just need to load the exten- be executed in the context of the loaded
such as the plugin’s name, version, sion into your browser. Open the link web page. Tampermonkey is based upon
and, important to us, the URLs of the about:debugging#/runtime/this-firefox. Greasemonkey [6], which currently only
web pages where the plugin should be Click on the button Load Temporary works in the Firefox browser. Tamper-
inserted (in this case, all URLs of the Add-on and load the manifest.json file. monkey, on the other hand, works with
domain perl.org). From now on, all pages from the domain the most common web browsers, and it
The second file you need contains the perl.org opened with this browser in- has a huge user community. The exam-
script you wish to inject. The script is stance will contain a brand-new Clickme ples in this article were produced on the
defined in the js parameter of the mani- button. You have successfully changed Firefox web browser on Linux Mint, but
fest.json file. In this example, the script the DOM and added a function that is they work also on other browsers, as
well as on other operating systems. You example I created before as a plugin. In videos using the Invidious front end [7].
can also use different browser extensions Figure 2, you see the script, which you Of course, Google is not happy about the
if they are available for your browser. just need to save using the menu that presence of an alternative open source
opens when you click on File. The result front end for YouTube that doesn’t allow
Installing the is the same as before, which gives a cer- Google’s tracking, and they have de-
Tampermonkey Extension tain confidence that what you did before manded that the developers take down
Tampermonkey is quite easy to install. In is working correctly. Invidious. Over the past few months,
Firefox, select Addons and themes then Google has been actively working to
choose Extensions in the menu on the left. Same Play with AI … shut down Invidious, so by the time you
Search for Tampermonkey, and click on For a more challenging example, there read this, this example might not give
the Tampermonkey icon to install. The are people who prefer to access YouTube the result shown here. In this case,
provider of the extension asks you to ac-
cept the necessary conditions regarding Listing 3: Substitute YouTube Links
privacy (Figure 1); you should read this // ==UserScript==
text carefully then choose which permis- // @name Replace YouTube Links on DuckDuckGo
sions you give to the provider. Monitoring // @namespace http://tampermonkey.net/
network traffic, you will notice that the // @version 0.1
provider of the extension is notified not // @description Replaces YouTube links with invidious.private.coffee in
only that you install his extension, but DuckDuckGo search results
every time you use it. Once you accept // @author Your Name
// @grant none
Listing 4: Substitute YouTube Links 2.0 are very powerful tools. You should
// ==UserScript==
know what you are doing – otherwise
// @name Replace YouTube Links on DuckDuckGo things could get complicated very fast.
// @namespace http://tampermonkey.net/
// @version 0.2 Another Way
// @description Replaces YouTube links with invidious.private.coffee in In the world of programming, the saying
DuckDuckGo search results goes, “There is more than one way to do
// @author Your Name
it!” I will show you a third way to get a
// @match https://*.duckduckgo.com/*
script up and running. If you open the
// @grant none
Tampermonkey extension, you will see in
// ==/UserScript==
the menu the option Find New Scripts.
This option opens a new menu contain-
(function() {
ing links that bring you to websites offer-
'use strict';
ing tons of ready-to-use user scripts. You
// Function to replace YouTube URLs with invidious.private.coffee
can perform a search to look for a script
function replaceYouTubeLinks() {
that fits your needs. But be prepared:
const links = document.querySelectorAll('a[href*="www.youtube.com"]'); These scripts might or might not work.
links.forEach(link => { Someone could have written the script for
link.href = link.href.replace a different extension, such as Greasemon-
("www.youtube.com", "invidious.private.coffee"); key, or for a different version of the exten-
}); sion you are using. Also, as the previous
}
example showed, timing could have an
impact on the operations. You should
// wait until the page has been loaded
therefore understand what you are doing
window.addEventListener('load', replaceYouTubeLinks);
before you use one of these scripts.
})();
window.addEventListener('load', U
replaceYouTubeLinks); Figure 3: Inspecting an HTML page using the browser’s built-in SDK.
Law and Ethics experience. The most interesting advan- Tampermonkey extension. Alternatively,
Before concluding this article, I want to tages are: you can use open source extensions
invite you to consider a few things. Your • Enhancing web pages – Tampermon- such as Violentmonkey [9]. You could
web browser is obviously your property, key enables users to modify the con- also choose to write your own extension,
whereas the web server you are contact- tent of web pages to add custom func- which is not very difficult. The same
ing with your browser belongs to some- tionality ranging from simple DOM holds for the scripts. You can develop
one else. I am not a lawyer, and the law manipulations to making AJAX calls. your own, let AI tools help you in writ-
in the field of informatics is rather com- This flexibility allows for a wide ing scripts, or download entire scripts
plex. I think that processing data you ob- array of enhancements, such as from trusted Internet sources.
tained from the Internet on your browser cleaning up websites, adding export Tampermonkey stands out as a valu-
is one thing. Constructing a web page to to PDF buttons, displaying word able tool for enhancing the web brows-
hack into a web server or modifying a counts, and much more. ing experience through user scripts. Ease
page to present to another user – or to • Customization and personalization – of use makes Tampermonkey accessible
masquerade as the original web server – By creating and utilizing user scripts, to a wide audience. However, users
is something entirely different. It is your individuals can tailor their browsing should remain mindful of legal issues
responsibility to act in accordance with experience to meet a specific need. and security considerations when em-
applicable legislation. Whether that need is improving the ploying custom scripts. Q Q Q
I have no idea how copyright applies usability of frequently visited sites or
to websites. In many cases, a copyright adding new functionalities, Tamper- Info
notice is listed somewhere on the site monkey scripts can significantly en- [1] The DOM W3 Schools: https://www.
with terms of usage. I suggest consider- hance the overall web-browsing w3schools.com/js/js_htmldom.asp
ing one ethical perspective. Some sites experience. [2] Introduction to the DOM:
rely on ads; without them, these sites • Learning opportunity – Writing user https://developer.mozilla.org/en-US/
could not stay online. Consider this scripts with Tampermonkey can serve docs/Web/API/Document_Object_
when trying to implement functionalities as an excellent learning opportunity Model/Introduction
such as ad blockers. for both beginners and experienced [3] Firefox Extension Workshop:
programmers. Tampermonkey pro- https://extensionworkshop.com/
Conclusions vides insights into web-page struc-
[4] How to Write Your Own Browser Ex-
Using Tampermonkey to write user tures, JavaScript, and the DOM.
tension:
scripts for web pages is a great way to Obviously all this comes with a price: se-
https://www.freecodecamp.org/news/
enhance and personalize the browsing curity. You must trust the supplier of the write-your-own-browser-extensions
[5] Tampermonkey:
https://www.tampermonkey.net/
[6] Greasemonkey: https://github.com/
greasemonkey/greasemonkey
[7] Invidious: https://invidious.io/
[8] IKEA 3D Model Downloader:
https://github.com/apinanaivot/
IKEA-3D-Model-Download-Button
[9] Violentmonkey:
https://violentmonkey.github.io/
Author
Reinhard E. Voglmaier
discovered his love for
computer science while
writing his diploma thesis
at the Max Planck Insti-
tute for Extraterrestrial
Physics in Germany. He started his career
as IT project manager and subsequently
took on the role of intranet manager in a
pharmaceutical company, overseeing web
services and addressing cybersecurity
concerns. Following his retirement, he
continues to lead the expert charter GRC
in Digital Health for ISACA Germany and
Figure 5: Downloading a 3D model: The button in the lower right is engaged in a computer linguistics proj-
labeled Download 3D was added by the script. ect at the University of Innsbruck.
In
Harmony
Using the Go Interface mechanism, Mike demonstrates
its practical application with a refresh program for local
copies of Git repositories. By Mike Schilli
V
acation time is travel time! I version until Git reported
like to take my laptop with me “up-to-date,” as well as clone
on long-haul flights. After all, repositories I previously only
the best ideas for new articles checked out on my home computer on collections in one fell swoop (e.g., “all
always come to me at the worst possi- my laptop to deliver all the resources I GitHub repos belonging to this user” or
ble times. But, without an Internet con- can access at home. “all subdirectories on a host with an SSH
nection, neither Google nor ChatGPT connection”). I want the GMF parser in
work, and GitHub is also out of reach Meta Format Go to read these individual entries or
for code ideas. Even the stuff I wrote Now the little helper can’t read my mind collections from the GMF file one after
previously is stashed away in Git reposi- (yet) and simply load everything that I the other and create matching objects
tories, and – worse still – the copies on think is important. That’s why I went for from them, all of which are then capable
my laptop are not always up to date. a meta file, as shown in Figure 1, to of using the Expand() method, from
That’s really annoying, because it specify the repositories and define the which the directories to be cloned –
means duplicating the work, which I directory names in each new develop- along with their URLs – are extracted.
want to avoid, or at least pesky integra- ment environment. It contains an array Later, the GMF parser will go through
tion and potential conflict-resolution in YAML format whose elements under all the entries in the YAML file in Listing
tasks later, when I look to reconcile the the keywords dir and url contain the 1 and call the Expand() method for each
texts I checked in while I was up in the clone directory and the URL of a reposi- one. There is not much to do in the first
air with an out of sync repository. tory I want to clone. Because this is entry in lines 1 and 2, because the YAML
Wouldn’t it be great to fire up a pro- GitHub repository metadata, the format, element already specifies the Git URL
gram on my laptop before the plane for historical reasons, should be called and the clone directory, so Expand() sim-
takes off to update the local copies of GitHub Meta Format (GMF), because I ply passes the combination to the clon-
all my checked-out Git repositories? It wrote it in Perl 15 years ago and intro- ing tool that then runs.
would need to sync the existing clones duced it in my column [1]. Fast forward The second entry in Listing 1, starting
on the laptop with the latest cloud to today, and there’s an opportunity to in line 3, uses the github-user-repos type
rewrite it in Go and at the same time to reference the repositories of a GitHub
Author demonstrate Go’s
Mike Schilli works as a cool interface Listing 1: repos.gmf
Lead Jörg_Stöber © Author, 123RF.com
user. This means that Expand(), in this Expand() methods do different things. arrays or passed around like others, and
case, needs to perform a search on The entries in the YAML file give me a whatever calls their methods is given the
GitHub, obtain the user’s repositories, list of different objects whose Expand() desired results, regardless of the actual
and generate the results: a list of Git methods do the right thing as a function object type under the hood.
URLs and their clone directories. The of the type. A loop then iterates across
third entry in Listing 1, starting in line 5, the objects and calls their Expand() meth- One Plugin for Every Task
of the ssh-user-repos type, tells Expand() ods while blissfully ignoring the actual To allow the GMF parser in Listing 2 to
to use SSH to log into the specified host, object types. collectively process the entries of differ-
list the Git directories there, and return a ent types, the parser defines the PluginIf
list of the directories as a result. Multifaceted in Go type, starting in line 17; the type has
In object-oriented programming, this pro- three functions. Applicable() checks
No Spaghetti Code cess is known as polymorphism, which whether the plugin can actually process
The parser calls Expand() three times, but comes from the Greek word for “many the current GMF entry from the meta
each time it achieves the result in a dif- forms.” What this translates to is that an file. If this returns true, the main pro-
ferent way. Of course, Expand() could identifier (i.e., a variable containing an gram calls the plugin’s Expand() function
find the currently correct algorithm in a object) can accept instances of different to obtain an array of cloneable reposito-
forest of if-else branches, but this is classes that all use the same method. Al- ries. If false is returned, the main program
confusing, not to mention difficult to test though the methods trigger different ac- moves on and tries the next plugin.
for correctness, expand, and maintain. tions as a function of the type currently in What the call to Expand() does now de-
In object-oriented terms, it makes more use, they have the same name and deliver pends on the plugin. The plugin for sin-
sense to write the solution to the the results in the same format. gle entries with a repository URL and
problem as different classes whose Unfortunately, Go is committed to clone directory, like in line 1 of Listing 1,
strict types, and just returns an array with a single ele-
the same variable ment – a variable of the Cloneable type
can never store containing these values. The code for
different types. this simple plugin is shown later in List-
This is where the ing 4. What all plugins have in common
Go interface type is that they offer a constructor (e.g., New-
enters the scene; GMFEntry()), which returns an object of
it determines the type in question that the main pro-
which functions a gram can use later on to call the func-
variable of a spe- tions standardized in the interface.
cific type offers.
Variables of type Plugin Wanted
interface can If the GMF parser later reads a YAML
then be stored in entry, this is returned as a GMFMetaEntry
Figure 1: The API call for a user’s repositories Figure 2: Every Github respository lists its own clone
returns JSON. URL, which is reported by the API.
type variable; FindPlugin(), starting in starting in line 23, contains three plu- Starting in line 28, the for loop then
line 22 of Listing 2, then rummages gin elements, all of which it creates by iterates through all the known plugins,
through all known plugins to find the using New...() to call their calling the Applicable() function for
right one. The plugins array slice, constructors. each one until true is returned. In
Listing 2: gmf.go
01 package main 33 return nil, errors.New("No applicable plugin found")
02 34 }
03 import ( 35
06 ) 38 Cloneables: []Cloneable{},
07 39 }
09 URL string 41
12 44 if err != nil {
14 Cloneables []Cloneable 46 }
16 48 p, err := g.FindPlugin(e)
21 53 if err != nil {
29 if plugin.Applicable(m) { 62
31 } 64 return g.Cloneables
32 } 65 }
Listing 3: parser.go
01 package main 17
16 } 29 }
Figure 3: One Gitmeta entry is all you need for all of a user’s GitHub repositories.
line 30, FindPlugin returns the reference AllCloneables() function in line 63 does contain the URL and target directory of
found in this way to the caller, or it re- no more than return the previous results a repository to be cloned. Like its big
ports an error in line 33 if it failed to to the caller as an array slice. brothers later, it is object-oriented and
find a suitable plugin. Listing 3 defines which entries are defines the NewGMFEntry() constructor
The GMF parser in Listing 2 is now permitted as elements of the long list of in line 5; the constructor returns a
object-oriented itself; line 36 defines its entries in the YAML file. An entry can structure that acts as the instance data
constructor. As the instance data, the specify a type. If this is missing, you are container, in typical Go style. In this
Gitmeta structure in line 13 contains an looking at a simple repository definition simple case, the structure remains un-
array slice of Cloneable types, each of consisting of the URL and its target populated; later, it will be used by the
which contains repositories to be cloned directory. caller as a reference for calling further
into their target directories (Figure 2). The Go GitMetaEntry type defines all plugin functions.
The AddGMF() function starting in line 42 permitted field names of the entries in The Applicable() function starting in
expects a file descriptor for an open the .gmf file starting in line 9. In addi- line 9 checks whether the repository’s
GMF file and calls parseGMF() (shown tion to the optional entry type, an YAML definition includes a field named
later in Listing 3) to read the file’s entry can contain the URL and Dir fields Type. If this field is missing, it’s a case
YAML content; this returns an array for a single entry, or the user for a for the plugin; the function returns true
slice of GitMetaEntry structures. GitHub repository (Figure 3), or the because e.Type == "" in line 10 evalu-
host and path for an SSH host that ates to true. Generating and returning a
Worker Assigned stores Git repositories. list of structures from the YAML entry
In line 48 FindPlugin() then then checks The parseGMF() function starting in line in Expand() in this simple case is merely
each array slice element to find the right 18 expects an open file descriptor, reads a formality; line 15 adds a single entry
processor, while the call to Expand() in YAML data from it, converts the YAML to the array slice of Cloneables. This
line 52 allows the plugin to discover configuration into a list of GitMetaEntry ob- concludes my first plugin!
which actual repositories of the Cloneable jects, and passes these back to the caller.
type the current entry actually points to. Plugin for GitHub
The for loop starting in line 56 ap- Simple Plugin What about a more advanced plugin,
pends each match to the Cloneables in- To get started, the plugin in Listing 4 is like one that fetches all repos in a us-
stance array, while the exported dedicated to simple entries that er’s GitHub account? Listing 5 shows
Listing 4: gmf-entry.go the plugin I built for this, following the previously used
01 package main
pattern.
It also comes with a constructor in line 18 which returns an
02
empty GMFGithubUser type structure to the caller. The Applica-
03 type GMFEntry struct {}
ble() interface function starting in line 22 examines the entry’s
04
type field and volunteers to take care of the entry if it finds the
05 func NewGMFEntry() GMFEntry { github-user-repos string there. Later, Expand(), starting in line
06 return GMFEntry{} 26, calls the githubProjectsOfUser() helper function from line
07 } 39 to contact the GitHub API and lists the specified user’s re-
08
positories in JSON format.
As you can see from Figure 1, what is returned in JSON is a
09 func (g GMFEntry) Applicable(e GitMetaEntry) bool {
jumble of data that lists all of the user’s repositories with all
10 return e.Type == ""
kinds of parameters, such as whether it is a fork of another
11 }
project. Because the cloning tool is only interested in original
12 repositories, line 57 discards all forks. Finally, Expand() returns
13 func (g GMFEntry) Expand(e GitMetaEntry) ([]Cloneable, a list of Cloneable structures to the main program.
error) {
Listing 5: gmf-ghuser.go
01 package main 34 clones = append(clones, Cloneable{URL: repo.SSHURL,
02 Dir: repo.Name})
03 import ( 35 }
05 "fmt" 37 }
06 "net/http" 38
29 if err != nil { 59 }
31 } 61
Listing 6: gmf-ssh.go
01 package main 31 URL: fmt.Sprintf("%s:%s/%s", e.Host, e.Path, dir),
02 32 Dir: ldir,
03 import ( 33 })
04 "bufio" 34 }
05 "bytes" 35
06 "fmt" 36 return clones, nil
07 "os/exec"
37 }
08 "strings"
38
09 )
39 func sshGitDirs(host string, path string) ([]string,
10 error) {
11 type GMFSSH struct {} 40 results := []string{}
12
41 cmd := exec.Command("ssh", host, "ls", path+"/*/
13 func NewGMFSSH() GMFSSH { config")
26 } 54 }
27 55 }
Listing 7: gitmeta.go
01 package main 20 }
02 21
03 import ( 22 gmf.AddGMF(f)
06 "os/user" 25 panic(err)
07 "path/filepath" 26 }
09 28 err = os.Chdir(gitDir)
11 if len(os.Args) != 2 { 30 panic(err)
12 panic(fmt.Errorf("usage: %s repos.gmf", 31 }
os.Args[0])) 32
15 35 if err != nil {
17 f, err := os.Open(cfg) 37 }
18 if err != nil { 38 }
19 panic(err) 39 }
starting at line 21. sshGitDirs() runs ssh Starting with the paths to the config loop then checks these, starting in line 33,
on the command line, which runs an ls files inside the repositories that have calling cloneOrUpdate() from Listing 8
command on the remote host to list the been found, line 53 truncates them to in each case.
Git repositories under the specified path. their last two parts and adds this relative This function in turn expects a Clone-
It is assumed that ssh is configured with directory name to the end of the results able struct and the path under which all
a key pair and works without manual string array slice. Back in Expand(), line 29 Git clones are stored. Prior to this, the
password entry. trims the frequently used .git suffix to main program has set gitPath to the git
create the name I directory in the current user’s home di-
Listing 8: clone.go want the Git clon- rectory; if you want something else, you
01 package main
ing tool to use for will need edit this section.
02
the local copy. There are now two options for the ac-
Line 31 then cob- tual cloning process: Either the directory
03 import (
bles together the with the clone already exists and only
04 "os"
URL for the repos- needs to be updated with git pull. Or it
05 "os/exec"
itory from the does not yet exist, and git clone in
06 "path"
hostname, the line 13 of Listing 8 creates a new local
07 ) path, and the re- copy of the remote repository.
08 pository’s direc-
09 func cloneOrUpdate(c Cloneable, gitPath string) error { tory. The result is Bringing It All Together
10 fullPath := path.Join(gitPath, c.Dir) a list of Cloneable To build a binary from all of the listings
11 _, err := os.Stat(fullPath) structures. in this issue, follow the usual steps:
12 if os.IsNotExist(err) {
14 _, err := cmd.CombinedOutput()
Action! git mod tidy
QQQ
MakerSpace
Make your microcontroller apps
safe and secure with Rust
Rust on a Device
Rust, a potential successor to C/C++, claims to solve some memory safety issues while
maintaining high performance. We look at Rust on embedded systems, where memory
safety, concurrency, and security are equally important. By Andrew Malcolm
F
or decades, C and increasingly for new code and for re-writing critical push button. A little later, I’ll show how
C++ have been the languages sections of existing code as a stepping to check if Rust supports a particular
of choice for microcontroller de- stone to a full Rust implementation. processor and/or architecture. STM32
velopment, with assembler re- With that being said, this article is devices are ARM Cortex based, and Rust
served for optimizations and start-up code. intended as a “getting started” guide: has excellent support for that architec-
Most vendors provide free development Adoption of Rust is a big step in a com- ture. This particular NUCLEO develop-
IDEs, and most of these use GNU compil- mercial environment, and one of the ment board, in common with many such
ers under the hood. Some of the IDEs best ways to evaluate a new language boards, has an on-board programmer
come with initialization code and generate is to try it! In today’s world of low-cost (typically another microcontroller), so a
device configuration code (choosing I/O development boards and free software USB cable hooked up to you Linux box is
functionality, etc.), so a device can be tools, all it takes is a little time and de- all you need to download, run, and
configured in a point-and-shoot manner termination. Then you can base your debug code on the board.
letting you concentrate on writing applica- decisions on some real-life experience. Development in Rust requires only the
tion code. Similarly, manufacturers of I/O There will be a lot of code in this arti- Rust toolchain and an editor. I’m going
devices such as sensors and wireless mod- cle – many of the following listings have to be using VS Code [5] with the rust-
ules supply drivers and example code. a filename – and you can get all those analyzer plugin [6], as this has excellent
C/C++ is an easy-to-learn language, but files from our download area [2]. support for Rust with code completion,
it’s also easy to abuse and to write buggy syntax highlighting, and so on, but there
code. Embedded code is expected to run Setting Up a Development are other solutions out there.
unattended, often in hostile environments Environment
where code updates are difficult if not im- I’m going to assume you’ve installed Cross Compiling
possible. Increasingly, these devices are In- Rust and its associated tools and got be- You’ll need the datasheet [7] and reference
ternet-connected. While this means easier yond a simple “hello world” program. If manual [8] for the chosen microcontroller.
code updates, it requires a significant not, you can follow the instructions on From the start, you can see that the micro-
amount of extra effort to do well, and iron- the Rust website [3] to get started. I’d controller has an ARM 32-bit Cortex-M4
Photo by Lucas van Oort on Unsplash
ically this very connectivity lays the device encourage you to become familiar with 32-bit processor with hard floating-point
open to nefarious access attempts. I know the rudiments of Rust by writing code support. You can use this information to
that there are tools available that help to for your Linux platform before moving tell Rust what to cross compile to. Visit
minimize the risk of bad code getting into on to an embedded environment. I will ARM’s developer website [9] for more de-
a product, and it is certainly not easy to use an STM32 development board, spe- tails: specifically the ARMv7E-M architec-
consider rewriting large legacy codebases in cifically the NUCLEO-L476RG [4] (Fig- ture and Thumb instruction set. Armed
another language, but I think that Rust [1] ure 1), but you could use almost any (no pun intended) with this information,
has come far enough and has sufficient development board, though it’s useful if you can visit Rust’s platform support page
advantages over C/C++ to be considered the board has at least one LED and a and find the thumbv7 target support [10].
By default, your Rust installation only provides support for the Cortex core and processor will jump to an entry in the in-
supports your host architecture, Linux. To includes linker instructions to ensure our terrupt vector table located at the begin-
add support for your target, simply type: code is properly located in the target ning of FLASH. This is taken care of in the
memory [12]. You can add this crate as a start-up code, so all you have to tell the
rustup target add thumbv7em-none-eabihf dependency with linker is where to find the memory. Add
memory.x with the following lines in the
Typing rustup show will confirm the sup- cargo add cortex-m-rt root of your project directory:
ported targets. To start a project, type:
this should add a dependency line to MEMORY
Now you can add the entry-point direc- RAM : ORIGIN = 0x20000000, LENGTH = 96K
Change your directory to the directory tive and a function that never returns. Your FLASH : ORIGIN = 0x08000000, LENGTH = 1024K
created in that command and start VS code should look like this (main-01.rs): }
brary and that your program does not fn entry_point() -> !{ target = "thumbv7em-none-eabihf"
this. Later you will add another directive } rustflags = ["-C", "link-arg=-Tlink.x"]
use panic_halt as _;
STM32L476RCTx
how the code is laid out in memory (see Then typing cargo embed will be enough to
Listing 1). It shows that the vector table The output shows it supports many vari- program and run your code on the target.
is located at the start of the flash mem- ants of the STM32L476, including our
ory, the program code (.text) 0x400 target. Now connect the target board to Runtime Debugging
bytes later, and it’s all of 0x8c bytes in a USB socket on your host. The power Before diving into programming the mi-
size. Any variables (.data) would be lo- LED should light. Type probe-rs list crocontroller’s I/O, I’ll deal with a debug-
cated in RAM, though in this case, with and you should see that it has detected ging technique which allows you to print
the program being so simple, the .data the target board. Your output may vary, data back to your host’s console. The first
segment has zero size. depending on the exact configuration: step is to add another crate with
Programming the Target The following debug probes were found: cargo add rtt-target
this code, you need one further tool, 56501320303658 (ST-LINK) (which provides a feature called real-time
cargo embed. This tool talks over USB to transfer, RTT) and a new statement to the
the companion processor on the target Let’s try programming the target: program:
Listing 1: Output of “Cargo Size” cargo embed --chip STM32L476RGT use rtt_target::{rprintln, rtt_init_U
print};
nucleo-l476rg-primer :
section size addr You should see an output similar to that in
.vector_table 0x400 0x8000000 Figure 2 – success: Your code runs! Note Modify the Embed.toml file you created
.text 0x8c 0x8000400 that the proper launch command was cargo above, and set enabled to true in the de-
.rodata 0 0x800048c embed and not cargo run, which would at- fault.rtt section. Then you can add
.data 0 0x20000000 tempt to run your program on the host. some print statements to your code (see
.gnu.sgstubs 0 0x80004a0 source code file main-02.rs). This will
.bss 0 0x20000000 fail to link, producing an undefined sym-
.uninit 0 0x20000000 bol error. You can fix it by adding a fea-
.debug_abbrev 0x11ab 0x0 ture to the cortex-m crate. Change the
.debug_info 0x223c7 0x0 appropriate line in Cargo.toml to this:
.debug_aranges 0x1348 0x0
.debug_ranges 0x195f0 0x0 [dependencies]
.debug_str 0x3b4da 0x0 cortex-m = { version = "0.7.7", U
.comment 0x40 0x0
features = critical-section-single-core"] }
.ARM.attributes 0x3a 0x0
.debug_frame 0x4154 0x0
Modify main.rs so that it looks like Fig-
.debug_line 0x1f26e 0x0
Figure 3: Real-time transfer lets ure 3 (main-03.rs). This should clear
.debug_loc 0x29 0x0
you see output from the embed- your terminal and print a list of ascend-
Total 0x9cc75
ded device (main-03.rs). ing numbers. As this data is exchanged
via in-memory buffers, it is very fast. prone. That’s a matter of taste though. cargo remove stm32l4
Embedded debugging is a whole topic in For a higher-level approach, like that cargo add stm32l4xx_hal
itself, and sometimes there is no substi- provided by ST’s hardware abstraction cargo clean
tute for a full gdb-type debugger, but layer (HAL), you have the choice of two
print statements like this will answer levels available in Rust crates. For the cur- Change Cargo.toml again, replacing
many questions such as “did my code rent device, one popular crate is stm32l4
reach this point?” or “what is the value which you can add via cargo add stm32l4. stm32l4xx-hal = "0.7.1"
of this register?” without interrupting Repeat the earlier test and make the LED
what can be time-sensitive code. Press flash using this approach. First modify with
Ctrl+C to return to the command line. your Cargo.toml file to specify the exact
microcontroller in use. Change stm32l4xx-hal = { version = "0.7.1", U
Configuring I/O Pins and features = ["rt", "stm32l476"] }
With vendor IDEs, you configure I/O pins Now change main.rs into the version in
for a user interface. For instance, you can to Figure 6 (main-06.rs). Compile and run
make port A pin 5 an output (it’s con- it. I’ve added an input for a push but-
nected to an LED) and port C pin 13 an stm32l4 = { version = "0.15.1", U ton, but otherwise the result is the
input (it’s connected to a push button). features = ["stm32l4x6"] } same – this code is more concise and
The IDE will generate the appropriate C/ easier to read.
C++ code for you and add it to your proj- Then change main.rs to look like Figure 5
ect’s startup code. Rust doesn't offer this (main-05.rs). The stm32l4 crate sticks Setting Up the Microcontoller
option, but of course, you can examine closely to the register names in the data- Clock Tree
the microcontroller data sheet, figure out sheet, so with a bit or careful study it By default, the STM32 processor runs
what values to write to what register, and should be clear what’s happening. For in- off an internal RC clock at 4MHz, so
dispense entirely with the IDE approach. stance, odr is the output data register, so you are not getting its best perfor-
I’ve annotated the code in Figure 4 odr5 refers to bit 5, which is the bit that mance. The delays I’ve added are clock
(main-04.rs) with references to the man- controls pin 5 of that particular port, in this dependent. If you set up the clock cor-
ual, to show how I found the values. I case port A. For example, it should be clear rectly with
have now managed to make the LED what the following in line 27 is doing.
blink using only direct register writes. If let mut flash = peripherals.FLASH.U
you, though I think in all but the most You can step up a level and use a HAL rcc.cfgr.sysclk(80.MHz()).freezeU
trivial cases it’s tiresome and error- crate. Run these commands: (&mut flash.acr, &mut
Figure 4: Make it blink – with direct register Figure 5: Register access via peripheral access crate
access (main-04.rs). (main-05.rs).
(main-07.rs), the LED should blink much rprintln!("{}", _info); Memory Management
faster. This still uses the internal 4MHz loop {} If you try to use a String or Vec type,
clock, but via a PLL, which increases the } you’ll notice they are not available, as
system clock frequency to 80MHz. If they are part of the standard library and
your board has an external crystal The modified version outputs something I have disabled it with #![no_std]. This
(usually 8MHz), you can use that as like this: leads to a thorny topic for embedded sys-
the primary clock source, and your sys- tems: memory allocation. Many projects
tem clock frequency will be much panicked at .cargo/registry/src/index.U avoid memory allocation altogether or re-
more stable (see below). However, using crates.io-6f17d22bba15001f/U strict its use to initialization, as there is a
cortex_m::asm::delay is clock dependant, stm32l4xx-hal-0.7.1/src/rcc.rs:719:13: risk of the heap becoming full or so frag-
so it’s time to use a proper delay mech- assertion failed: pllconf.n >= 8 mented that it cannot allocate any further
anism that runs from sysclk. This is space. In order to use strings and vectors
shown in Figure 7 (main-08.rs). In that So you can see the the PLL configuration in embedded Rust, you can use the alloc
version, the LED flashes at a more accu- is not correct, and an assertion in the clock crate. This comes as part of the distribu-
rate one-second period. configuration has failed. There are limits to tion, so there is no need to change Cargo.
If you set the clock to 40MHz, you’ll the frequencies that can be generated. If toml. However, if you use this crate and
notice that the code does not run. you set the clock frequency to 64MHz, the attempt to create a string like this:
What’s going on? Let’s improve our code will run again. Note that the LED
panic handling to see if there is a panic period stays the same – this is all sorted extern crate alloc;
occurring. Replace the line out internally. If you want to use an exter- use alloc::string::String;
use panic_halt as _; which is known as the HSE clock source, let s = String::from("I am a string U
you can set it up as shown in Listing 2. allocated on the heap");
with
Next Steps you will get a compile time error. You
use core::panic::PanicInfo; So far, I have created a very simple Rust have to supply your own allocator, as the
program running on a microcontroller. alloc crate only supplies the types, but no
run I’ve dealt with clock configuration and implementation of the heap allocator. The
toggling an I/O pin. The stm32l4xx_hal excellent Embedded Rust book [17] shows
panic!("testing panic handler"); repository [14] has an examples folder how to implement a simple allocator that
demonstrating how to set up and use the never frees up memory. Of course, that
before the end of the loop, and add this various I/O facilities of the STM32, such might cause problems in some circum-
panic handler at the end of the file: as I2C, SPI, UARTS, and USB. The crate stances, but if you carefully instrument
documentation is another good source the allocation, it may work for you. Alter-
#[inline(never)] for details on how to use this library. natively, you can look for a more sophisti-
#[panic_handler] The “Working with Legacy Code” box cated allocator at crates.io. I’ll give the
fn panic(_info: &PanicInfo) -> ! { shows how to integrate old C code. simple approach a try. First, modify
Figure 6: I/O access with an abstraction layer Figure 7: A proper delay mechanism is derived from
(main-06.rs). sysclk (main-08.rs).
arm-none-eabi-gcc -c -mcpu=cortex-m4 U
wonky_math_library.c -o wonky_math_library.o
arm-none-eabi-ar rs libwonky_math_library.a U
wonky_math_library.o
[target.thumbv7em-none-eabihf]
In order to call your library from Rust, you must define its
prototype:
extern "C"
{
pub fn wonky_add(a : i32, b: i32)-> i32;
}
and then you can call it. Figure 8 shows a simple, complete pro-
gram that demonstrates this; the output at the host terminal is
“Calling wonky_add to compute 2+2. Answer = 5” – clearly, I have
some work to do on my math library! Calling external functions Figure 8: Calling C/C++ code from Rust (main-10.rs).
02 MEMORY
03 {
07 }
08
09 /* heap */
10 _heap_start = ORIGIN(RAM2);
methods, but the name is a little mis- work to build an equivalent applica- Figure 9: This program uses an
leading as they don’t work in the same tion. Crates.io offers many helpful li- allocator to access a second RAM
way as in C/C++. For instance, braries, but they are not all highly de- bank (main-11.rs).
veloped. Vendors of sensor chips and
struct Test { the like will often provide drivers, but choose from. So, you would have to ei-
data : u32 only in C/C++. So you have to either ther write a large chunk of your appli-
} rewrite them in Rust, if that has not al- cation from scratch in Rust or settle for
ready been done, or use the mixed lan- the mixed-language solution. Q Q Q
impl Test { guage facilities I have described. The
fn new() -> Test { more you do this, of course, the less ef- Author
Test{data: 0} fective the use of Rust will be in elimi- Andrew Malcolm
} nating that class of bugs that occur in (MIET, CEng) is a re-
} C/C++code. Consider for example, a tired hardware and
firmware engineer.
driver for an LTE (mobile) module, writ-
He maintains a keen
simply returns an instance of Test on the ten in C/C++, a TCP/IP stack, and an interest in engineering
stack that will be lost when it goes out of SSH server, which might make up a in general and building embedded projects.
scope. Stack overflow is not addressed by communications feature for a remote He is an avid user of Linux and all its
the Rust language and remains a problem data collector. It’s unlikely right now available open source and free engineer-
ing tools. While not tinkering with elec-
for embedded systems. The usual ap- that you would find complete implemen- tronics or software, he plays the bassoon
proach is to pre-fill the bottom of the tations of all of that in Rust, whereas in in local orchestras. He can be contacted at
stack with a known (canary) value and C/C++ you would have several to [email protected].
periodically check if that value has been
overwritten (see stack-check.rs [2]). Info
[1] Rust: https://www.rust-lang.org/ [9] ARM developer website:
Wrap Up [2] Source code for this article: https://developer.arm.com/
I've shown how to write an embedded https://linuxnewmedia.thegood.cloud/ Processors/Cortex-M4
Rust program, load it to a device, and s/5Rzx9tQW2FJ6N3Z [10] Rust thumbv7 target support:
check that it runs. I’ve also covered Rust [3] Rust installation: https://doc.rust-lang.org/nightly/rustc/
crates that assist with setting up the I/O https://www.rust-lang.org/tools/install platform-support/
peripherals, as well as shown how to catch thumbv7em-none-eabi.html
[4] STM32 NUCLEO-L476RG:
and deal with Rust panics and, with RTT https://www.st.com/en/ [11] Rust crates: https://crates.io/
in place, report back problems to the host. evaluation-tools/nucleo-l476rg.html [12] cortex_m_rt crate: https://docs.rs/
In production, a panic could log an [5] VS Code: https://code.visualstudio.com/
cortex-m-rt/latest/cortex_m_rt/
error and reboot for, say, an illegal array [13] probe.rs installation: https://probe.rs/
[6] rust-analyzer plugin: https://code.
reference. That’s preferable to the situa- docs/getting-started/installation/
visualstudio.com/docs/languages/rust
tion in C/C++, where these references [14] STM32L4xx HAL repository:
[7] NUCLEO-L476RG datasheet:
might go undetected, corrupting data or https://github.com/stm32-rs/
https://www.st.com/resource/en/
causing other unwanted behavior. If your stm32l4xx-hal
datasheet/stm32l476je.pdf
device is networked in any way, it presents [15] Install C compilers: https://learn.arm.
[8] NUCLEO-L476RG reference manual:
an attack surface to potential bad actors, com/install-guides/gcc/cross/
https://www.st.com/resource/en/
and here all the checks that Rust provides reference_manual/rm0351-stm32l47 [16] bindgen: https://rust-lang.github.io/
become even more valuable. xxx-stm32l48xxx-stm32l49xxx-and- rust-bindgen/
The current downside in adopting stm32l4axxx-advanced-armbased- [17] Embedded Rust: https://docs.
Rust is that it’s potentially a lot more 32bit-mcus-stmicroelectronics.pdf rust-embedded.org/book/collections/
MakerSpace
=[MZ̆NZQMVLTaÅTM[PIZQVO
NWZIZMUW\MTWKI\QWV
7Є\PM/ZQL
A battery-powered WiFi hotspot can provide useful services like
file sharing even when you're off the grid. A Pi Zero 2 W as the
hotspot with ownCloud installed does the trick. By Dave McKellar
I
am lucky enough to have access to Getting Started
my extended family’s remote It might sound easy, but it took me
cabin. It’s beautiful and remote about two weeks to figure this all out. I
(Figure 1), but there is no grid – no started with the goal of running Next-
electricity or Internet, not even by cell cloud on a device that uses the smallest
service. I set up a solar-powered WiFi amount of power possible, as power is
access point that hosts exactly one web- in short supply. I knew that the “W” in
site: a place to share files. This lets the Raspberry Pi Zero W meant built-in WiFi
different people who visit the cabin ex- and the “Zero” indicated a small, low-
change info with the next group who is power form factor. My first attempts
staying. It’s kind of fun, too: The shared with a Pi Zero W model (released in
data includes practical things like the 2017) showed that it was too slow, so I
new phone number of the fellow who ordered a Pi Zero 2 W (released in 2021).
delivers propane and playful things like It has four cores, and its speed is
photos of people swimming. adequate. Lead Image © Tithi Luadthong, 123rf.com
Figure 1: The cabin is located in an isolated area; its only power source is the solar panel.
ownCloud Setup
You can use the commands in Listing 1
to install and setup ownCloud like I did.
Connect your Pi to the local network via
an Ethernet cable and do not connect it
to any WiFi network – you’ll need the
WiFi to set up your own hotspot later. In
the terminal, log in on the Raspberry Pi
Zero via SSH and run sudo su to gain
admin access for all the following
commands.
Figure 2: The Raspberry Pi Zero 2 W connected to a monitor, keyboard First, use systemctl to disable Blue-
and mouse for development. tooth to save some power (line 1) –
don’t uninstall it because that will stop
I also bought two different cases to try. appliance, but I wanted more control. WiFi. Next, remove some packages we
Some have more openings than others, Ultimately, I selected a regular Raspberry aren’t going to use. I ran
and I wanted black to be low-key. Since Pi OS install with ownCloud instead of
this project only requires WiFi and no Nextcloud (ownCloud, Nextcloud's apt --installed list
Figure 4: Change the login dialog so that your guests will not try to enter an email address.
of the database it should use. You’ve al- rewrite module (you will use this later) This makes captive portal [6] detec-
ready created a database named owncloud with the a2enmod rewrite command. For tion work. Recent smartphone and com-
and noted the password in the previous the name of this server, I’m using lodge. puter operating systems will check a
step. During this setup, you’ll need to local because that’s a proper fully quali- known non-secure URL when first con-
provide a username and password for fied domain name (FQDN), which will not necting to an access point to see if
the admin account that you also must require a DNS lookup to resolve. Set the they’re online. (For example, some ver-
remember. name of the server in the hostname file: sions of Windows check http://www.
I added a group called regular (via msftconnecttest.com/connecttest.txt
admin/Users/Groups/add group) and made echo lodge.local > /etc/hostname which returns Microsoft Connect Test.)
a user called user with password user on I first thought that returning anything
the same user and group management and add the IP address of that name by but the expected text would make the
page. By default, ownCloud asks for an appending a line to /etc/hosts: client OS detect a captive portal, but that
email address to validate a new user, but didn’t work. From experimenting, it ap-
you can click on the cog icon in the lower 10.42.0.1 lodge.local pears that the client OS requires an
left corner and enable the Set password HTTP redirect to reliably detect a captive
for new users option: That will replace the (You will remove this entry later.) At the portal, so that’s what this Apache direc-
email address input field with a password end of /etc/apache2/apache2.conf add: tive does. It needs to be a temporary redi-
field (Figure 3). As a minor tweak, I rect so that it’s done every time.
changed the prompt message in /var/www/ ServerName lodge.local You might ask: Why do you want the
html/owncloud/core/templates/login.php access point to be detected as a captive
so that it asks for Username instead of Now things are getting interesting. Re- portal? If it isn’t, the client OS will say
Username or email (Figure 4). member this server isn’t going to be on “no connection,” thereby misleading the
ownCloud will only allow users from the Internet. Later, when you set up the user. Yes, it’s true that this access point
certain trusted domains. Since my domain DNS, you’re going to redirect every do- has no connection to the Internet, but it
is lodge.local, I added it to file /var/ main (hostname) to here. However, that does have its own website. When a cap-
www/html/owncloud/config/config.php alone isn’t quite right. You need to tive portal is detected, the user will be in-
that defines an array called check what host the browser is asking structed to log in, upon which the user
trusted_domains. for. If it’s not your host, then you need will see the website, or more precisely,
to redirect the browser to your host. In whatever content you put in /var/www/
Setting Up the Web Server /etc/apache2/sites-enabled/000-de- html/index.html, replacing Apache’s de-
With Apache installed, now it’s time to fault.conf, add the code from Listing 3 fault page. Listing 4 shows a minimal
customize it. First, enable the Apache at the end of the file. Then restart HTML file that links to the ownCloud
Apache via: login page; Figure 5 shows the slightly
What About HTTPS? more polished version I’ve created for the
systemctl restart apache2 lodge (1) and how users can navigate
Do you want or need SSL/TLS? There
are two possible uses: to intercept
HTTPS requests to other websites and
Listing 3: Apache rewrite Rule
01 ServerName lodge.local
redirect them to your homepage, and
to present your homepage with HTTPS. 02
homepage doesn’t seem so great. 02 nmcli con modify lodge 802-11-wireless.mode ap 802-11-wireless.band bg ipv4.
compatible instructions online [8]. 04 nmcli con modify lodge connection.autoconnect yes
Figure 5: The homepage (left) contains instructions on how to log in to the local ownCloud service.
from there to the ownCloud login (2), the and in the [Resolve] section of its configu- systemctl start systemd-resolved
top folder in the shared filesystem (3), ration file /etc/systemd/resolved.conf I set
and the picture folder (4). This will send all requests to a DNS server
Note, I’ve only been dealing with the # Use dnsmasq running on port 5353 on this machine –
unencrypted HTTP protocol. For HTTPS, DNS=127.0.1.1:5353 you’ll see why in a second. Perhaps con-
see the “What About HTTPS?” box. fusingly, you will be using two different in-
and then start the service with stances of dnsmasq for two different tasks:
Creating the Hotspot
So far, I have not turned the Raspberry Pi
Zero into a WiFi access point. Listing 5
shows the necessary commands which,
again, you need to run with root privi-
leges. First use the Network Manager
command-line tool (nmcli) to create an
“open” (password-less) network (lines
1-3). Then make it auto-start at boot time
(line 4). I also add the command
1. One instance runs as a regular dae- port=5353 my name on the homepage to inspire a
mon, controlled by systemctl and using address=/#/10.42.0.1 bit of confidence.
the configuration file /etc/dnsmasq.d/ If you’re interested in a more complex
lodge.conf. It will be doing DNS only. Now restart the dnsmasq service with solution that also grants access to the
2. Another instance is started by Network- Internet (where available), you can
Manager doing DHCP only. It does not systemctl restart dnsmasq check out dedicated captive portal solu-
read /etc/dnsmasq.conf or /etc/ tions, such as Nodogsplash [9] and
dnsmasq.d/lodge.conf; it starts on the fly you can also remove the lodge.local openNDS [10], but they were not
from parameters in the /etc/NetworkMan- entry from /etc/hosts now. The ad- needed for this project. Q Q Q
ager/system-connections/lodge.nmcon- dress= line will make the DNS server
nection (Network Manager format) and return 10.42.0.1 (the Raspberry Pi’s Info
/etc/NetworkManager/dnsmasq-shared.d/ WiFi IP address) as the answer to all [1] Raspberry Pi power supply documen-
lodge.conf (dnsmasq format) files. DNS queries. Try it: Running ping ex- tation: https://github.com/raspberrypi/
I also need to install the second dnsmasq ample.com should return a reply that documentation/blob/develop/
service. Run: starts with: documentation/asciidoc/computers/
raspberry-pi/power-supplies.adoc
apt install dnsmasq 64 bytes from lodge.local (10.42.0.1)
[2] NextPi:
https://github.com/sky321/nextpi
Then create a new file /etc/dnsmasq.d/ Finally, I will configure the instance of
[3] Raspberry Pi Imager:
lodge.conf with the following two lines: dnsmasq that’s started by NetworkMan-
https://www.raspberrypi.com/software/
ager; it deals with DHCP and hands out
IP addresses to clients that connect to [4] SURY: https://sury.org/
my hotspot. Create a file /etc/Network- [5] Adding the SURY repo:
Manager/dnsmasq-shared.d/lodge.conf https://gist.github.com/janus57/
and add this line: 37b079a383dd0507149bd94fd35053d1
[6] Captive portal: https://en.wikipedia.
dhcp-option=114,"http://lodge.local" org/wiki/Captive_portal
[7] RFC 8910
This will inform some WiFi clients
https://www.rfc-editor.org/rfc/rfc8910
about the captive portal mode, and it
[8] Self-signed certificates:
follows RFC 8910 [7]. It tries to achieve
https://peppe8o.com/self-signed-
the same goal as my redirect configura-
certificate-https-in-raspberry-pi-with-
tion of the Apache server. When this is
apache
all put in place, users should see the
lodge access point and be able to con- [9] Nodogsplash: https://github.com/
nect to it (Figure 6). nodogsplash/nodogsplash
[10] openNDS: https://github.com/
Conclusion openNDS/openNDS
So there you have it: a user-friendly
way for trading files via WiFi on low Author
power (Figure 7). Sometimes convinc- Dave McKellar earned a
ing people to use a project is the hard- Computer Science de-
est part. I am pleased to report that gree in the 1980s from
some extended family members have the University of Water-
loo, Canada. Since then,
told me that they’re using it – quite
he’s worked as a pro-
Figure 7: The Raspberry Pi sits in probably for things I never imagined. grammer for a variety of
a black case and is mounted to Some were initially reticent since they companies with Windows and Linux. He
the rafter (circled). It is attached didn’t know where the thing came enjoys canoeing near the remote cabin
to a power supply. from. In retrospect, I should have put mentioned in this article.
QQQ
MADDOG’S
DOGHOUSE
The stakeholder approach of open source broadens the pool of who
Jon “maddog” Hall is an author,
educator, computer scientist,
and free software pioneer
who has been a passionate
can access, influence, and benefit from information technologies. advocate for Linux since 1994
when he first met Linus Torvalds
BY JON “MADDOG” HALL and facilitated the port of
Linux to a 64-bit system. He
serves as president of Linux
FOSS and economic models International®.
n 1999, I was honored to work with several groups of peo- DEC, Hewlett-Packard, and others. Some companies, like IBM,
Learn It!
Flashcards are a fast and effective way to memorize pertinent facts for your
next exam. Anki takes this time-honored trick in a direction you never could
have imagined in the days of those classic 3x5 cards.
BY MARCO FIORETTI nki is a multiplatform, open source digital libraries – called libxcb-xinerama0, libxcb-cursor0,
different ways.
This will create a directory with the same name of
Installation and Upgrades the archive, containing the same or similar files
At the time of writing, there are two branches of shown in Listing 1.
Anki for Linux, one built with version 5 and one with The first and biggest file is the actual Anki exe-
version 6 of the same Qt graphic libraries that are cutable program, which is just over 100MB, and
the foundation of the KDE Desktop Environment. the second is the source code of its man page.
Both branches also depend on three external The install.sh and uninstall.sh scripts are those
you should run, with root privileges, to install or
Listing 1: Anki Archive Contents uninstall Anki for all the users of your system.
#> cd anki-24.06.3-linux-qt6/
By default, the first script will place all those
#> anki-24.06.3-linux-qt6$ ls files (including the uninstall.sh script!) in /usr/
local/share/anki, and then create a link to the Anki
anki executable in /usr/local/bin. After that, the script
anki.1 will set up the Anki man page and all the Anki en-
anki.desktop tries and icons in your system menus and desktop
anki.png background.
anki.xml
Alternatively, you may try Anki without installing
anki.xpm
anything, by just launching the executable file
install.sh
from the prompt, in the installation folder:
README.md
uninstall.sh
#> ./anki
answer. The button you press will determine how Its only problem is the one I already mentioned: Fig-
much time will pass before Anki shows you that ure 2 actually creates one “Basic” note, that is a
card again. The intervals can be changed, of data structure which just by coincidence generates
course, and you can change the status and just one card with two sides, thus continuing (to-
many other parameters for each card in the gether with the lack of current, clear documenta-
More menu of Figure 4. tion) to hide the true power of Anki.
Besides text and images, you can insert math Until now, that is. I’ll show how to create a more
formulas in your cards by typing them in TeX for- sophisticated note that can generate two comple-
mat (e.g., \(\sqrt{x}\)" to add the square root of x) mentary cards by entering the corresponding data
selecting that text, and pressing the button labeled just once. For simplicity, the data will be French-to-
fx in Figure 2. Anki will add the formula, nicely type- English word pairs, for a French language course.
set with the MathJax system [8]. A similar proce- From the Anki main window click on Add, select
dure is available for chemical equations [9]. You Basic (and reversed card) as the note type, and then
may use LaTeX to insert the same type of content, click on Fields, as shown in the top left of Figure 5.
and even musical notation, but at least for formulas In the Fields pop-up window (bottom-right cor-
and equations, MathJax (which is integrated in ner of Figure 5), delete any preconfigured fields
Anki) would be a zero-setup solution more than ad- and add three new ones: one for French words,
equate to the task. one for their English equivalents, and (just as ex-
The interface of Figure 2 is very simple to use, ample) one for the corresponding page of your
even if you want to use audio or video in your cards. French-to-English dictionary.
Then, click on Cards to configure
the templates of all the cards that
Note type can generate. As you can
see in the top-left corner of Figure 6,
the note I chose has two card types:
The first is for what I will call “direct”
questions, which in my case would
ask the English translation of a
French word. The second would be
for the “inverse” question, French
terms for English words. For both
card types, you must define what to
show on the front and back sides.
Looking at the Back Template panel
of Figure 6, you can see that the back
(the answer side of each card of this
type) will have the same content as
the front side, followed by a two-line
answer containing the English
Figure 5: Configuration of an Anki note (not card!) for a specific topic
begins by defining its fields.
Figure 6: After note fields, you must configure the templates of the cards Figure 7: The same operation shown in Figure 6, but for the reverse ques-
that will display them. tion and answer of an Anki note.
Figure 9: The two specular Thanks to this, if your brain remembered Eng-
cards generated by the sin- lish-to-French translations much more easily than and hide it whenever it presents you the correspond-
gle note created for the French-to-English ones, Anki could show you the ing card. To hide more words, just repeat the pro-
Ami/Friend word pair. French-to-English much more frequently than the cess. As in the French language example, it is possi-
ble to create multiple cards from the same note by
adding more clozes. A cloze note with this text:
kernel.
To create IO notes, choose the corresponding Linux Distributions::Debian and one called Linux
note type, load into the note the image that should Distributions::Slackware would be two sub-
be occluded, and then use the additional buttons decks of the upper-level deck about Linux
that appear in the Anki note editor to hide as distributions.
many parts of the image as desired and also add That said, with Anki it is important to not get
captions. Then, click on the Image Occlusion Mode carried away with partitioning decks in smaller
button, to the left of the button with the cursor, to sub-decks, for the simple reason that the smaller
choose between Hide All, Guess One and Hide one, a deck is, the more predictable the order of its
Guess One. The first mode hides all the areas you cards become. You may end up memorizing the
masked and reveals them one at a time; the sec- order of the answers and find yourself unable to
ond only hides one area. remember all of them separately.
The right way to classify your notes in any way
Card and Note Maintenance you want without this problem is to give each of
Anki includes a card and note browser with two them tags (compare with the bottom of Figure 2),
separate views, one for notes and one for cards. which you can then organize into trees as desired
Both views, distinguishable by the different col- by dragging and dropping them onto each other in
ors of the view selector, are partially visible in the the browser shown in Figure 10.
collage in Figure 10, where you can also check
that the data I entered for the sample French lan- Anki Data Formats
guage course indeed produced three notes and At the beginning of this article, I observed that I
six cards. really like how Anki saves and exports its internal
As soon as you have more than a 100 notes, data, because it makes it easy to automatically
you should check the browser regularly to see create or analyze how many flashcards I want, in
how many notes or cards are in each state, many ways.
change the state, or add flags and tags to orga- Here is what I mean: Your Anki user profile con-
nize them better. The browser is also the place tains, besides a directory for compressed back-
where you can arrange cards or notes in different ups in ZIP format, another directory called collec-
orders, or search all the those that contain spe- tion.media and two files called collection.anki2
cific text, even saving the most frequent searches and collection.media.db2. They are nothing other
with custom names. than two single-file databases in the SQLite3 for-
mat that are fully supported on all operating
Anki Decks and Tags systems.
As powerful as notes are, if they were the only way This means that you can restore them with any
Anki had to organize content, things would get SQLite recovery tool if something bad happens
very messy as soon as you tried to study more (and if it does, Anki will let you know!). Besides, if
than one subject. you aren’t satisfied by all the reports that Anki gen- Figure 10: The Anki browser
In practice, this is no problem because Anki lets erates (see Figure 11), you can create your own by is the one-stop shop where
you assign any notes and their cards to one or directly querying those databases, even aggregat- you can keep all your notes
more decks, regardless of the note type, and also ing the statistics of multiple users! and cards under control.
tag them in any way desired.
Having one deck for every topic ensures that
when, for example, you need to refresh your mem-
ory about Linux administration, or whatever else
you need to know to pay the bills, Anki won’t dis-
tract you with questions about video game history
or any other hobby you may have.
Besides this obvious advantage, Anki decks have
an even bigger one if you build or customize them
yourself, rather than using decks made by some-
body else without any changes. When you assem-
ble a deck by choosing all the right questions as I
mentioned above, deciding which note is better for
memorizing each piece of information, how much
context it should have, and so on, you have already
started to learn and memorize, before having actu-
ally reviewed a single Anki card.
To make things even easier, each deck can
have as many sub-decks as desired, using two
colons as a level separator. That is, a deck called
Equally interesting are Anki’s import and export Listing 2’s format is easy to decode: After a
capabilities, both accessible from the File main simple, self-explaining header, there is one note per
menu. You can export just one deck or all of your row, with tab-separated columns that contain note
user profile as ZIP archives, which you can share type, deck, fields, and tags. The reason why this
with other users with the .akpg (Anki package) makes me happy is that if this format is easy to
suffix for decks and .colpkg (Anki collection pack- read, it’s also easy to write! In other words, it would
age) for your whole profile. be quite easy, with the tons of text-processing tools
But you may also export (and subsequently im- available on Linux, to generate a separate deck for
port in any another Anki instance) all your notes in each student of a entire course, and that’s just one
plain-text format, and this is the part I really like. use case. Aren’t open formats wonderful?
To see what I mean, check out Listing 2, the Anki
export file of all the notes I created for this tutorial, Conclusions
telling Anki to include everything but the unique The distinction between cards and notes should re-
note identifier it uses internally. ally be explained better in the documentation and
Figure 11: The only problem with the Anki statistics about your study may be how many of them there are.
presented better in the interface. I hope this article really match your needs, or if you don’t regularly re-
helps to clear up this matter. In addition, the online fine the content of your decks.
documentation available at the time of writing With this advice in mind, I think anyone who
did not always match the Anki version I reviewed feels overwhelmed by how many things they
(24.06.3): For example, it listed different card should remember should at least give Anki a
states than the ones I saw in the Anki browser. serious try. Q Q Q
Anki has lots of add-ons of all sorts, but for a tool
like this I would recommend to not looking at them Info
before becoming really familiar with the note/card
[1] Anki: https://apps.ankiweb.net/
duality and all the basic functions, lest you find your-
self playing with gadgets and statistics more than [2] “Augmenting Long-Term Memory” by Michael
actually learning from your cards. I mean, notes. A. Nielsen, July 2018:
http://augmentingcognition.com/ltm.html
On the same note, as good as Anki is at manag-
ing flashcards, all its functions and all the statistics [3] AnkiDroid Flashcards: https://play.google.
in Figure 11 (and that’s just some of them!) will do com/store/apps/details?id=com.ichi2.anki
very little for you if you don’t get into the habit of [4] Anki web interface: https://ankiweb.net
using Anki regularly, with schedules configured to [5] Spaced repetition:
https://en.wikipedia.org/wiki/Spaced_repetition
The Author [6] “What is the difference between a card and a
note?” (2015): https://www.reddit.com/r/Anki/
Marco Fioretti (https:// comments/3x58fb/what_is_the_difference_
mfioretti.com) is a free- between_a_card_and_a_note/
lance author, trainer, and
researcher based in [7] “Note vs Card???” (2023): https://www.reddit.
Rome, Italy, who writes com/r/Anki/comments/17s355r/note_vs_card/
about digital rights issues [8] MathJax: www.mathjax.org
at https://mfioretti. [9] Chemical equations with MathJax:
substack.com. https://mhchem.github.io/MathJax-mhchem/
LINUX VOICE FOSSPICKS
FOSSPicks Nate explores some top FOSS tools, including the latest
Sparkling gems and new
releases from the world of
Free and Open Source Software
Gnome 47
n September 18, the redundant Videos folder. I also Gnome Calendar also contains numerous bug fixes and
System cleaner
Czkawka
’ve always felt one of the previous version (6.10) is also
see
ing: For example, comments
appeared in green and objects
in blue. I was particularly im-
pressed to see that the None at-
o quote the project tribute for objects appeared in
CAST-text
latforms such as Face- defaults to BBC News. However,
3D-model viewer
Exhibit
’ll never forget the first time I lists instructions on the GitHub
Valuta
menu to switch to alternate
sources such as Moeda.info or
Google Finance, though the app
warns the latter is unstable. I
eaders of FOSSPicks will found proof of this after trying to
LibreQuake
here are few gamers who beta. Like
LibreQuake’s textures and weapons work flawlessly. Currently there are five levels – press the Project Website
space bar to load after entering a portal. https://librequake.queer.sh/
Hosted hypervisor
VirtualBox
ince 2008, Oracle’s cross- for a newly created VM. This pres-
Concessio
’m of the belief that if you’ve file permissions work in Unix
A
BY RUBÉN LLORENTE
break of the new millennium was the Why Make the Effort
golden age of video games, at least for
Many retro games are still available for pur-
nostalgic microchip heads such as myself. This
chase in one form or another. It’s therefore
era represents a sweet spot in which computers worth considering why you should make a
were powerful enough to represent 3D environ- backup of an old retail version of a game,
ments, display decent graphics, and play high- considering you could just buy it again for
quality soundtracks. Still, the video game indus- less than $5 if the CD you have were to break.
try had not evolved yet into the greedy machine The GOG.com [1] store maintains an enor-
it eventually became, inventing aggressive mon- mous catalog of retro PC games, and they
etization schemes and coming up with in-game support the available titles so they can run
purchases, loot boxes, or intrusive digital rights on modern operating systems. The over-
management (DRM) mechanisms. Back then, whelming majority of their games are DRM-
the usual way of obtaining a video game for free. Why aren’t these an option?
your PC or game console was to (gasp!) walk up The main reason is that what is often found
Figure 1: A collection of PC to a store and purchase a physical copy. A PC for sale is not exactly the retail version you
video games from the late game would take the form of a CD (or many, for have, and the retail version you have is actu-
1990s and early 2000s. large titles) which contained all the required ally not for sale at all. This is especially no-
Many of these titles are not data to install the software and play. No Internet ticeable when you purchased non-English-
available in retail form any- connection was required. language games as a kid: The studio that de-
more due to licensing and I am the sort of person who keeps old stuff veloped the game back then may no longer
trademark issues. around forever and does not toss it into the trash hold the rights for the translations, which
means Spanish, French, etc., versions of the
game aren’t available anywhere for purchase.
If you have a retail version in your language,
you may as well treat it as irreplaceable.
Quite often, studios which released a game
back in the late 1990s or early 2000s ended
up releasing one or more modern, updated
versions later. The newer version is usually
easy to find, because old versions are
dropped and all effort goes into supporting
the most recent one. An example that comes
to mind is Imperivm III, a game which was
very popular in Spain. The HD remaster is still
for sale, but no seller carries the original any-
more. These upgraded versions may contain
gameplay changes you are not on board
with, however, so if you liked the old iteration
of the game, the only way to ensure you can
play it in the future is to archive it yourself.
bin so long as it is in working order. Therefore, I suitable for the task, but fear not, because I will ex-
have a meaningful collection of PC games in a amine useful alternatives in this article.
vault (Figure 1). While reorganizing my storage
space, it occurred to me that many of these Backing Up
games aren’t easily playable on modern comput- The gold standard for backing up a CD into an
ers – the ones I can realistically obtain – despite image is, without any shadow of doubt, cdrdao [3].
being in an excellent state of preservation. This It can generate an image from any healthy CD
thought immediately set me on a quest to find out
how to enjoy these gems from the golden age and
how to preserve them for the future (for more on Copy Protection
why, see the “Why Make the Effort” box). By the end of the ‘90s, the video game industry had entered the dark
ages. Reproducing and distributing illegal copies of CDs at scale had
The Problems become cheap, and publishers considered that it was time to prevent
There are two tasks to complete when you decide users from making full copies of the games. Copy protection was born.
to archive a video game for posterity. The first is (See more about PlayStation games in the “What About PlayStation
saving each title in question in a format that is Games?” box.)
easy to replicate (for backup purposes) and also There were many copy protection mechanisms for CDs. Some of them
easy to run the game from. The second is pre- were crude, such as pressing the retail copies of the game with large
serving or simulating a system capable of running amounts of defective sectors. The idea was that domestic optical read-
the game in question, because you often can’t in- ers would error out while trying to make a backup image and encounter-
stall a game from 1995 on a modern operating ing so many broken sectors. Other anti-copy mechanisms were a bit
system (OS) directly. smarter, and CDs would be pressed with a small number of defective
Saving an early game CD to your hard drive is sectors with manipulated error-correction data. When playing the game
not a complex task. Publishers of old games from the original CD, the game would scan the CD for the defective sec-
weren’t worried about people making full copies of tors, whose position was known, and refuse to play if such sectors
the games. Instead, they were concerned about weren’t present. However, when trying to image or copy the CD, regular
having the games ripped, stripped of their music CD copying software would locate the bad sectors, check the manipu-
and cinematics, compressed, and distributed in a lated error correction data, interpret the bad sector as an accidental
degraded form through illegal channels. This scratch, and correct it. Therefore, any backup copy of the game would
means anti-piracy safeguards were fairly unintru- lack the defective sectors and refuse to run.
sive and didn’t prevent the user from making legiti- The most cunning anti-copy mechanisms would analyze the geometry
mate backups. Such protections could require you of the CD and use data position measurements (DPM). In a nutshell,
to keep the CD in your optical reader while you DPM allows the game to map physical sectors on the CD by measuring
played and implement some simple checks to en- how long it takes the optical reader to move from a specific sector to an-
sure you actually had the CD (such as looking for other specific sector. The game then refuses to run if the topology de-
a file in the CD or checking the CD label). Such tected this way does not match the topology of the original CD. Retail
mechanisms cause no problem if you own a retail CDs are pressed rather than burned, and domestic CD burners cannot
copy or intend to play from a legitimate backup. replicate specific topologies, which makes producing a working copy im-
possible with domestic equipment. In addition, common image formats
Most Linux users will immediately think that back-
such as ISO or BIN/CUE pairs don’t contain the topology information
ing up such a game is as simple as putting the CD
necessary to fool copy protection.
in the tray and executing as root:
The good news is that distribution of games via physical media is con-
# dd if=/dev/cdrom of=game_image.img
sidered obsolete these days, so there has been no meaningful develop-
ment in CD copy protection for a long time. Meanwhile, software solu-
tions have developed in order to beat these primitive forms of DRM. The
The command above will generate a raw image of
bad news is that breaking copy protection might be illegal in your juris-
the CD, which will act as an ISO file for all intents
diction and even giving instructions to do so may be forbidden.
and purposes. This, however, will be insufficient
when archiving games whose CDs use complex Fortunately, many game publishers have realized it makes no sense to
or non-standard structures. For example, many keep enforcing CD copy protection and are giving their customers alter-
natives to keep playing games bought in the ‘90s. For example, the pop-
games would be sold in multitrack CDs, with one
ular Warcraft III and its expansion received official no-CD patches from
track containing the video game itself and the rest
Blizzard that allowed its users to bypass CD checks, which in turn made
of the tracks containing the music (such as Age
it possible to play Warcraft III from a backup image created with conven-
of Rifles in Figure 2). The dd command cannot
tional legal tools. On the other hand, Valve will deliver many old titles to
recognize these arrangements and will often fail
you via Steam as long as you have the serial number that’s glued to the
to produce a good copy. On the other hand, many box of the original copy. It isn’t ideal, but it might be an option.
commercial games, especially around the early
If you wonder if any of your games use anti-copy mechanisms, or want
2000s, were manufactured specifically so that it
to know if there are official patches from the manufacturer, the PCGam-
was impossible to save or clone its CD (see the
ingWiki [2] is likely to offer that information.
“Copy Protection” box). Therefore, dd is not
the tool I will use to convert the TOC file to CUE basic steps required to run a game. Once it is in-
format, applying the converter directly will result stalled, the next step is to create a folder to use as
in a backup with a reversed byte order. Failing to your MS-DOS directory:
account for the endianness swap with mixed-
mode CDs (the ones which combine data and $ mkdir ~/DOSGAMES
tively on it. There are also DOS emulators that run You’d have to substitute $blocks by the number of blocks obtained from
on modern operating systems. Among these, DOS- isosize.
Box is the most popular. DOSBox is a specialized Tests performed on my machines show that dd alone will transfer just
tool for running DOS games, and it has reached the required data into the image without the need for passing it a num-
such a level of maturity that commercial software
ber of blocks manually, which suggests to me the above advice is badly
vendors often distribute old DOS applications bun-
outdated. However, this advice is so prevalent that I consider it deserv-
dled with DOSBox. This emulator has also given
ing of being left here for reference.
birth to many forks that are worth a look. See the
“DOSBox Forks” box for more information.
Installing DOSBox in Devuan is as easy as DOSBox Forks
# apt install dosbox DOSBox is a popular piece of software that follows a, to put it mildly,
conservative approach to development. It has a reputation for rarely ac-
DOSBox has many interesting features, such as cepting outside contributions, and its development cycle is very slow.
the ability to interface with MIDI software devices,
As a result, many DOSBox forks have appeared. For example, DOSBox-X
but for the sake of brevity I will touch only on the
[7] is a variant with a deep feature set, capable of running even on early
Windows operating systems. In fact, the developers’ stated goal is “to
Listing 1: ~/example.conf
01 [autoexec]
eventually make DOSBox-X a complete emulation package that covers
02 IMGMOUNT E ~/game.cue -t iso
all pre-2000 DOS and Windows 9x-based system scenarios.”
03 MOUNT C ~/DOSGAMES Feel free to check the list of forks offered by DOSBox Staging [8].
Enter 86Box
As a solution, I find 86Box to be sufficient for
early Windows 95 and 98 games. 86Box is a pro-
gram capable of emulating old computers up to
the BIOS level and beyond. It lets you build a retro
virtual machine to your liking, selecting the com-
ponents you need from a vast menu of options.
Its focus is on emulation accuracy, and it’s often
recommended for people who want an authentic
experience without using a real retro computer.
Disadvantages are still many. The price you pay
for experiencing an authentic Windows 9x ma-
chine is also experiencing its many woes, such as
installing Windows, searching for drivers, and
Info
[1] GOG.com: https://www.gog.com [9] DOSBox list of supported applications:
[2] PCGamingWiki: https://www.dosbox.com/comp_list.php?
https://www.pcgamingwiki.com/wiki/Home letter=a
[3] cdrdao: https://cdrdao.sourceforge.net/ [10] DOSBox wiki:
[4] Endianness: https://www.dosbox.com/wiki/GAMES
https://en.wikipedia.org/wiki/Endianness
[11] Wine application database:
[5] PCSX-Reloaded: https://ps1emulator.com/
https://appdb.winehq.org/
[6] FreeDOS: https://www.freedos.org/
[12] 86Box releases at GitHub:
[7] DOSBox-X: https://dosbox-x.com/
https://github.com/86Box/86Box/releases
[8] DOSBox forks:
https://github.com/dosbox-staging/ [13] VOGONS retro community:
dosbox-staging/wiki/DOSBox-forks https://www.vogons.org/
Figure 7: Master of Dimensions, a graphic adventure from 1996, does not run so well for me. Notice the dismal emulation speed, at 58 percent.
QQQ
NEWSSTAND https://bit.ly/Linux-Magazine-catalog
Linux Magazine is your guide to the world of Linux. Monthly issues are packed with advanced technical
articles and tutorials you won't find anywhere else. Explore our full catalog of back issues for specific
topics or to complete your collection.
#288/November 2024
Smart Home
If you listen to megavendors like Google and Amazon, the only path to a smart home is
through the cloud, but the Linux community has a better way. We'll show you some open
source smart home tools with no cost and no spying.
On the DVD: Rocky Linux 9.4 and MX Linux MX-23.3
#287/October 2024
Ollama
Many Linux users are intrigued by Large Language Model (LLM) tools like ChatGPT, but if you
really want to be methodical about testing and experimenting, why get tangled in the cloud?
Ollama lets you run LLMs locally on a home computer.
On the DVD: Debian 12.6 and Clonezilla 3.1.3-16
#286/September 2024
Git Ready
The Git version control system is an integral part of the Linux environment. If you’re looking
for a better foundation in Git, or if you already know the basics and are ready to start building
Git into your own custom apps, we’ll make you Git ready.
On the DVD: openSUSE Leap 15.6 and Tails 6.4
#285/August 2024
Kernel Expoilts
Is Linux secure? Only if you keep up with the patches. This month we take a close look at how
intruders attack unsafe versions of the Linux kernel through known and well-publicized exploits.
We’ll show you how to set up your own out-of-date kernel to practice on, and we’ll introduce
you to some of the tools and techniques attackers use to gain root access.
On the DVD: AlmaLinux 9.4 Boot DVD and Fedora Workstation 40 Live
#284/July 2024
Laptop Security
In the scary world of the Internet, “more secure than Windows” still isn’t secure enough. If
you want to keep your traveling systems safe from the clutches of the espionage economy,
you’ll need some extra help. We show you how to outfit your laptop with the extra defenses
you’ll need for life on the road.
On the DVD: Ubuntu Budgie 24.04 LTS and Rescuezilla 2.5
#283/June 2024
AI Tools
Everyone is fascinated with AI right now, but at the end of all the articles and interviews and
research, it is fair to ask, what can I do with it really? This month we highlight some AI-based
tools that will help you build your own chatbot, sharpen photo images, and more.
On the DVD: Nobara 39 and Manjaro 23.14 Gnome
FEATURED EVENTS
Users, developers, and vendors meet at Linux events around the world.
We at Linux Magazine are proud to sponsor the Featured Events shown here.
For other events near you, check our extensive events calendar online at
https://www.linux-magazine.com/events.
If you know of another Linux event you would like us to add to our calendar,
please send a message with all the details to [email protected].
Events
SC24 Nov 17-22 Atlanta, Georgia https://sc24.supercomputing.org/
Open Source Monitoring Conf. Nov 19-21 Nuremberg, Germany https://osmc.de/
PyCon AU 2024 Nov 22-26 Melbourne, Australia https://2024.pycon.org.au/
Cephalocon Dec 4-5 Geneva, Switzerland https://events.linuxfoundation.org/cephalocon/
Open Source Experience Dec 4-5 Paris, France https://dev.events/conferences/
open-source-experience-3nlxf4ch
KubeCon + CloudNativeCon Dec 11-12 IndiaDelhi, India https://events.linuxfoundation.org/
CodeMash Jan 14-17 Sandusky, Ohio https://codemash.org/
FOSDEM 2025 Feb 1-2 Brussels, Belgium https://fosdem.org/2024/
State of Open Con '25 Feb 4-5 London, United Kingdom https://stateofopencon.com/
Kickstart Europe 2025 Feb 4-5 Amsterdam, Netherlands https://www.kickstartconf.eu/
SCaLE 22x March 6-9 Pasadena, California https://www.socallinuxexpo.org/scale/22x/
FOSS Backstage March 10-11 Berlin, Germany https://25.foss-backstage.de/
SUSECON 25 March 10-14 Orlando, Florida https://www.suse.com/susecon/event-details/
CloudFest 2025 March 17-20 Europa-Park, Germany https://www.cloudfest.com/
Images © Alex White, 123RF.com
Contact Info
Editor in Chief
Joe Casad, [email protected]
WRITE FOR US
Linux Magazine is looking for authors to write articles on Linux and the tools of
Associate Editor
the Linux environment. We like articles on useful solutions that solve practical
Amy Pettle
problems. The topic could be a desktop tool, a command-line utility, a network
Copy Editor
Aubrey Vaughn monitoring application, a homegrown script, or anything else with the potential
News Editor to save a Linux user trouble and time. Our goal is to tell our readers stories they
Jack Wallen haven’t already heard, so we’re especially interested in original fixes and hacks,
MakerSpace Editor new tools, and useful applications that our readers might not know about. We
Hans-Georg Eßer also love articles on advanced uses for tools our readers do know about – stories
Managing Editor that take a traditional application and put it to work in a novel or creative way.
Lori White
We are currently seeking articles on the following topics for upcoming cover
Localization & Translation
Ian Travis themes:
Layout • Cool Rasp Pi Projects
Dena Friesen, Lori White • Linux Shortcuts and Hacks
Cover Design • System Rescue
Lori White
Cover Image Let us know if you have ideas for articles on these themes, but keep in mind that
© pitinan and raptorcaptor, 123RF.com our interests extend through the full range of Linux technical topics, including:
Advertising • Security
Jessica Pryor, [email protected] Advanced Linux tuning and configuration
•
Marketing Communications
• Internet of Things
Gwen Clark, [email protected]
Linux New Media USA, LLC • Networking
4840 Bob Billings Parkway, Ste 104 • Scripting
Lawrence, KS 66049 USA • Artificial intelligence
Publisher • Open protocols and open standards
Brian Osborn
If you have a worthy topic that isn’t on this list, try us out – we might be interested!
Customer Service / Subscription
For USA and Canada: Describe your idea in 1-2 paragraphs and send it to: [email protected].
Email: [email protected]
Phone: 1-866-247-2802
(Toll Free from the US and Canada) Authors
For all other countries:
Email: [email protected] Thomas Boele 32 Andrew Malcolm 56
www.linux-magazine.com Zack Brown 12 Dave McKellar 64
While every care has been taken in the content of the
magazine, the publishers cannot be held responsible Bruce Byfield 6, 22, 38 Vincent Mealing 71
for the accuracy of the information contained within
it or any consequences arising from the use of it. The Joe Casad 3 Mike Schilli 48
use of the disc provided with the magazine or any
material provided on it is at your own risk. Mark Crutch 71 Tim Schürmann 16
Copyright and Trademarks © 2024 Linux New Media Nate Drake 82 Koen Vervloesem 26
USA, LLC.
No material may be reproduced in any form Marco Fioretti 74 Reinhard Voglmaier 42
whatsoever in whole or in part without the written
permission of the publishers. It is assumed that all Jon “maddog” Hall 73 Jack Wallen 8
correspondence sent, for example, letters, email,
faxes, photographs, articles, drawings, are supplied Rubén Llorente 88
for publication or license to third parties on a non-
exclusive worldwide basis by Linux New Media USA,
LLC, unless otherwise stated in writing.
Linux is a trademark of Linus Torvalds.
All brand or product names are trademarks of their !
respective owners. Contact us if we haven’t credited !"#"# " !# $! %& !
$%%&' ( )(
your copyright; we will always correct any oversight. *$%%%%)+, (
#$& ' ( # "
#$)& *' (# ! !
Printed in Nuremberg, Germany by Kolibri Druck. , -% &. & /"
#$+& " , - .
0 1. ,++&%% *2 3 45 *
Distributed by Seymour Distribution Ltd, United !6 6 %73(8- !8 3& 82-!"9 #$/& " ! !
#
0 1. ,++&%% *: +' & &% &; & 6% %%
Kingdom 45 *%)&
" , # ""
0, #
!6 6 %73(8- !8 3& 82-!" $& ' ( " !
Represented in Europe and other territories by:
" 1% +0 1. ,++&%%% *%)&8 $)&*' ( ! !
Sparkhaus Media GmbH, Bialasstr. 1a, 85625 <+ &8 + <+ &
$+& " ! !
Glonn, Germany. 6& 4% & 8!6 6 %73(8- !8 3& 82-
$/&0, # ! !
!"
Linux Magazine (Print ISSN: 1471-5678, Online = 0 % +8!6 6 %73(8- !8 3& 82-!" " 0, # " !
&>) 8!6 6 %73(8- !8 3& 82-!"
ISSN: 2833-3950, USPS No: 347-942) is published !43 & 3+ ?-,808!6 6 %73(8
" , # !!
monthly by Linux New Media USA, LLC, and dis- - !8 3& 82-!"9- 7) +&%-. &7) %+ ! , # !
;1:86 %% & 8; 8;&1 ( "
tributed in the USA by Asendia USA, 701 Ashland 2 3 6 +) +&%8 & %8 +4 )&- & (: +&%
!
""@ ""@
Ave, Folcroft PA. Application to Mail at Periodicals 43 &: + & & & * ,1 *6 +%8
& %8 & )&- & % 1
Postage Prices is pending at Philadelphia, PA and - %: % ) ++& .& + 1 )%
additional mailing offices. POSTMASTER: send ad-
#" $2&3 $21 &
dress changes to Linux Magazine, 4840 Bob Billings $%% * &0& -. 1&!
" , # $20&3 $21 &
$ & *( ) * &1 *& %)+ )%* &1% & +
Parkway, Ste 104, Lawrence, KS 66049, USA. 1. ;3 0 &786% %% &8!"#"#! $4 - $1##(1 55&
December 6
Issue 290 / January 2024
Alternative
Office Suites
Most Linux distributions come bundled with the LibreOffice
suite, but Linux is all about choice, and a number of other
options exist in the wild. If you’re getting restless and want to
explore the contenders for word processing, accounting, and
presentations, look for next month’s issue, where we study
some of the leading office alternatives.
Also inside:
• Weather Cam
• Metadata in Digikam
• Bash Tricks for Web Maintenance
• Manage Your VPNs with WireGuard Easy
• And much more!
Please note: Articles could change before the next issue.