<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[AndroidLab]]></title><description><![CDATA[AndroidLab]]></description><link>https://androidlab.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 28 Oct 2026 04:40:56 GMT</lastBuildDate><atom:link href="https://androidlab.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Porting SSH to AROS on a Raspberry Pi: handles, tasks and shutdown bugs]]></title><description><![CDATA[Host-key prompts, AmigaDOS handles, resource cleanup and remote-command limits: a code-based look at BebboSSH AROS 1.0.5.]]></description><link>https://androidlab.hashnode.dev/porting-ssh-to-aros-on-a-raspberry-pi-handles-tasks-and-shutdown-bugs</link><guid isPermaLink="true">https://androidlab.hashnode.dev/porting-ssh-to-aros-on-a-raspberry-pi-handles-tasks-and-shutdown-bugs</guid><category><![CDATA[Raspberry Pi]]></category><dc:creator><![CDATA[Michele Dipace]]></dc:creator><pubDate>Thu, 15 Oct 2026 10:00:56 GMT</pubDate><content:encoded><![CDATA[<p>A server that accepts a connection, copies a file and then crashes when it exits is not a finished port. Shutdown can expose a runtime mismatch that a successful login never exercises.</p>
<p>The aarch64 work in BebboSSH AROS 1.0.5 is a useful case study. The difficult parts were not all in the protocol code: a host-key question consumed the wrong input, a console check received the wrong kind of handle, and cleanup crossed allocation boundaries.</p>
<p>I maintain the AROS fork of Stefan "Bebbo" Franke's BebboSSH. This article examines the versioned source and release checklist, rather than presenting new benchmarks. The target is <strong>AROS running on a Raspberry Pi</strong>, not Raspberry Pi OS or another Linux distribution. The documented hardware validation is on a Pi 400; it is not evidence that every ARM board works.</p>
<h2>1. Same source tree does not mean the same runtime</h2>
<p>The fork shares source across three public targets:</p>
<table>
<thead>
<tr>
<th>Target</th>
<th>Runtime distinction</th>
<th>Non-interactive remote commands</th>
</tr>
</thead>
<tbody><tr>
<td>i386, alt-abiv0</td>
<td>AROS SDK path</td>
<td>Child task</td>
</tr>
<tr>
<td>x86_64</td>
<td>Minimal runtime, with compatibility wrappers</td>
<td>Synchronous backend</td>
</tr>
<tr>
<td>aarch64, raspi-aarch64</td>
<td>AROS SDK path, following i386</td>
<td>Child task</td>
</tr>
</tbody></table>
<p>These differences affect behavior after compilation. On x86_64, a long remote command can occupy the daemon. On i386 and aarch64, the child-task backend allows it to remain responsive. The binaries and their release kits are not interchangeable.</p>
<p>The cryptography also has a packaging difference from the classic Amiga build. The AROS tools link the inherited crypto code statically, rather than requiring a separately installed <code>libcryptossh.library</code>. That avoids one executable/library version mismatch, but increases the amount of code embedded in each tool.</p>
<h2>2. A host-key failure can start before the user answers</h2>
<p>Before 1.0.5, the native client could print the first-connection host-key question and then fail with <code>failed to verify the host</code> before the user had a chance to respond.</p>
<p>The relevant boundary was AmigaDOS command startup. <code>RunCommand()</code> leaves command-line input available in <code>Input()</code> for argument processing. The key-confirmation path could consume those leftover bytes as the answer.</p>
<p>The release adds an input flush in the AROS startup path:</p>
<pre><code class="language-cpp">// Drop command-line input left for ReadArgs().
Flush(Input());
</code></pre>
<p>This is an abbreviated excerpt, not a complete portable SSH initialization routine. The x86_64 minimal runtime also needed a compatible wrapper.</p>
<p>The important distinction is that the fix restores the conversation with the user. It does not remove host-key verification. An unexpected key change still needs investigation.</p>
<p>When a prompt appears to answer itself, inspect where its input stream came from before changing the validation logic.</p>
<h2>3. A C stream and an operating-system handle are different things</h2>
<p>Another client issue involved console detection. In this AROS environment, <code>stdin</code> is the C library's <code>FILE</code> object. <code>IsInteractive()</code> expects an AmigaDOS file handle.</p>
<p>The AROS branch now asks about the handle returned by <code>Input()</code>:</p>
<pre><code class="language-cpp">escape = IsInteractive(Input());
</code></pre>
<p>The distinction matters even when a compiler lets an inappropriate value reach an API. The old console check caused raw cursor-key handling on aarch64 in the documented case.</p>
<p>This is an easy mistake to make when porting a program that already supports several environments. Familiar names such as standard input can hide incompatible representations. Follow the ownership and type expectations of the receiving API, not just the name of the object being passed.</p>
<h2>4. Successful allocation is not proof of compatible cleanup</h2>
<p>The aarch64 SDK declares convenience functions such as <code>CreatePort()</code> and <code>CreateExtIO()</code> through <code>clib/alib_protos.h</code>. In this build, they could bind to <code>amiga.lib</code>, while the existing release paths used incompatible cleanup.</p>
<p>The result was particularly misleading: the daemon could run, but exiting it crashed.</p>
<p>For the aarch64 keyboard resources, 1.0.5 uses matching Exec operations on both sides:</p>
<pre><code class="language-text">CreateMsgPort()       -&gt; DeleteMsgPort()
CreateIORequest(...)  -&gt; DeleteIORequest(...)
</code></pre>
<p>The timer request similarly moves to <code>CreateIORequest()</code> and a corresponding <code>DeleteIORequest()</code> during cleanup. This describes the aarch64 branch; the minimal-runtime branch retains its own wrappers.</p>
<p>The broader lesson is not that one allocator family is universally better. It is that the selected constructor, allocator and destructor must agree in the actual linked binary. Header declarations and compatibility libraries are part of that investigation.</p>
<h2>5. A timeout response is not cancellation</h2>
<p>The remote-execution limits are as important as the target list.</p>
<p>On the i386 and aarch64 child-task path, a command still running after 30 seconds gets a timeout notice and exit status <code>124</code>. The command can continue running. A caller must not interpret that status as confirmation that the work has stopped, especially before retrying something that writes data.</p>
<p>A command typed inside the interactive SSH shell is a separate case: it runs inside the daemon and can hold up other connections. This is not a complete Linux-style PTY environment. Remote pipes, redirection and unsupported stdin-driven commands are deliberately rejected rather than treated as supported features.</p>
<p>For automation, start with a short command:</p>
<pre><code class="language-sh">ssh user@AROS_IP Version &gt; aros-version.txt
</code></pre>
<p>Here, the PC's shell handles <code>&gt; aros-version.txt</code>. That is different from putting the redirection inside the quoted command sent to AROS.</p>
<h2>6. Validate the failure paths and the public package</h2>
<p>The <a href="https://github.com/kaffeine1/bebbossh-aros/blob/v1.0.5-aros-aarch64/docs/AROS_AARCH64_RELEASE.md">versioned aarch64 checklist</a> records:</p>
<ul>
<li>Five crypto self-tests and 100 sequential logins.</li>
<li>SCP/SFTP transfers in both directions, byte comparisons and shorter-file overwrites.</li>
<li>Twenty zero-delay stress iterations, totalling 80 transfers up to 1 MiB.</li>
<li>Native console input, including cursor sequences followed by a character in the same packet.</li>
<li>Shutdown with <code>Break</code>, followed by restarting the daemon.</li>
</ul>
<p>Those are project-recorded results, not tests rerun for this article. They also have boundaries. High-volume debug logging to a console froze the Pi during stress, while the default logging level passed. QEMU <code>raspi3b</code> with <code>usb-net</code> had very slow reception and a failed upload that did not reproduce on the Pi 400.</p>
<p>The package checks matter too: validating local build output does not prove that the public archive contains those binaries. The release smoke script can download the published archive, check expected hashes and reject unintended hosted artifacts.</p>
<p>Finally, pin claims to the release. The three public AROS 1.0.5 tags point to <a href="https://github.com/kaffeine1/bebbossh-aros/commit/188e3017833eddbe72331595d54111353799c11b"><code>188e301</code></a>. The later <a href="https://github.com/kaffeine1/bebbossh-aros/commit/e3599e236e5c4907989d5c8cdeb2e12c20b8bfbc"><code>e3599e2</code></a> fix for logging without a shell channel is on the subsequent development branch, not in those 1.0.5 packages.</p>
<h2>What this port does not establish</h2>
<p>These fixes do not turn the underlying system into a hardened general-purpose SSH appliance. Full PTY behavior remains incomplete. The porting notes describe entropy-generation limitations and a best-effort fallback rather than an available system CSPRNG in this environment. Remote accessibility and modern cipher support do not remove those constraints.</p>
<p>What the port does illustrate is a useful debugging sequence: trace the input source, verify the API's handle type, match resource lifecycles, distinguish timeout from cancellation, and test the exact package users download.</p>
<h3>Sources and disclosure</h3>
<ul>
<li><a href="https://github.com/kaffeine1/bebbossh-aros">BebboSSH AROS repository and upstream attribution</a>.</li>
<li><a href="https://github.com/kaffeine1/bebbossh-aros/blob/v1.0.5-aros-aarch64/AROS_PORTING.md">Porting notes at the aarch64 1.0.5 tag</a>.</li>
<li><a href="https://androidlab.it/en/bebbossh-aros-105-ssh-on-raspberry-pi/">Related AndroidLab guide: installation, architecture differences and operational limits</a>.</li>
</ul>
<p>I maintain this fork and write for AndroidLab. The source project is derived from Stefan "Bebbo" Franke's BebboSSH and is licensed under GPLv3 or later; the code excerpts above are adapted from that project. This article was prepared with AI assistance and checked against the versioned source and release documentation. No new hardware test is claimed.</p>
]]></content:encoded></item></channel></rss>