diary at Telent Netowrks

The ANT is my friend, it's blowing in the wind#

Sat, 06 Mar 2021 14:46:16 +0000

A few weeks ago I won some bike rollers on Ebay, and once I'd mastered the basic skills (pedalling without falling over, stopping without falling over, starting without falling over without holding onto the door jamb), I started looking for some way to measure what I was doing. Another Ebay purchase later and I was the owner of a Garmin GSC10 speed/cadence sensor. (There are two standards for wireless fitness equipment: ANT+, which is the older one, and probably obsolescent, and Bluetooth Low Energy, which is newer but is based on Bluetooth, therefore probably unreliable. Also, in terms of what I could find on Ebay, BTLE is double the price for any brand I'd heard of.)

But the sensor is only half of the solution: I also need something to display the values, and as I already have a handlebar mount for my phone I decided that an Android app would be the thing.

There is more than one route to persuading an Android phone to receive ANT readings: you can

Then I needed an app.

 As a cyclist
 I want speed and cadence displayed in big numbers
 So I can see them even when the wind is making my eyes water
   and the sun is shining on the phone display

Apps for ANT+ sensors also seem to be comparatively thin on the ground. IpBike seems to be the de facto standard, but after trying it a few times I was struck by acute NIH, and decided it would be more fun to write my own than to figure out whether I could configure it for my needs ...

Three weeks later I'm not sure it is more fun, but it's certainly a learning experience. https://github.com/telent/biscuit

Her name is Oreo#

Fri, 12 Feb 2021 13:47:14 +0000

I am at a point somewhere along the way of a long yak-shaving journey ("I wonder if the MSM8953 SoC supports ANT+ in hardare and it just needs enabling in the Android software?") which involves rebuilding Android for my phone. There seem to be very few ROMs for the Moto G5 Plus ("potter") that are still being maintained, and even fewer of them that have build instructions that (a) work as described; (b) comprise fewer than 30 manual steps. Do Android ROM developers not do CI builds? If this was all GPL I could make a strong case it's in breach. ("The source code for a work means the preferred form of the work for making modifications to it [...] all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable."). Yes, I know, volunteers, spare time, teeth of gift horses, etc etc. End rant

Anyway, so far I am doing the following and it has not yet blown up

1) using the docker image from LineageOS for Microg

2) invoking it as follows

docker run \
    -e "BRANCH_NAME=lineage-15.1" \
    -e "DEVICE_LIST=potter" \
    -e "SIGN_BUILDS=false" \
    -e "SIGNATURE_SPOOFING=restricted" \
    -e "INCLUDE_PROPRIETARY=false" \
    -e "WITH_SU=true" \
    -e "CUSTOM_PACKAGES=GmsCore GsfProxy FakeStore MozillaNlpBackend NominatimNlpBackend com.google.android.maps.jar FDroid FDroidPrivilegedExtension " \
    -v "/$HOME/src/android/l4mg/lineage:/srv/src" \
    -v "/$HOME/src/android/l4mg/zips:/srv/zips" \
    -v "/$HOME/src/android/l4mg/logs:/srv/logs" \
    -v "/$HOME/src/android/l4mg/cache:/srv/ccache" \
    -v "/$HOME/src/android/l4mg/keys:/srv/keys" \
    -v "/$HOME/src/android/l4mg/manifests:/srv/local_manifests" \
    lineageos4microg/docker-lineage-cicd

3) with this manifest in $HOME/src/android/l4mg/manifests/roomservice.xml

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
	<project name="LineageOS/android_external_bson" path="external/bson" remote="github" revision="cm-14.1" />
	<project name="LineageOS/android_device_qcom_common" path="device/qcom/common" remote="github" revision="lineage-15.1" />
	<project name="LineageOS/android_packages_resources_devicesettings" path="packages/resources/devicesettings" remote="github" revision="staging/lineage-15.1" />
	<project name="boulzordev/android_device_motorola_potter" path="device/motorola/potter" remote="github" revision="lineage-15.1-64" />
	<project name="boulzordev/android_vendor_motorola_potter" path="vendor/motorola/potter" remote="github" revision="lineage-15.1-64" />
	<project name="boulzordev/android_kernel_motorola_msm8953" path="kernel/motorola/msm8953" remote="github" revision="lineage-15.1-64" />
</manifest>

Worthy of note:

As I write this, it has been building for ~ 30 minutes and not fallen over yet, so things are looking vaguely promising

[  8% 8343/95970] target thumb C++: libv8src_32 <= external/v8/src/builtins/builtins-constructor.cc

Apparently it's done 8% of something

Update: Fri Feb 12 19:57:48 GMT 2021

It works! It built a buch of stuff in zips/potter/ including the file lineage-15.1-20210212-UNOFFICIAL-potter.zip which I installed from Recovery using the instructions at https://wiki.lineageos.org/devices/peregrine/install Yes, that's not the same phone, but it's close enough to use the same procedure

Led astray#

Sat, 30 Jan 2021 13:46:06 +0000

There are probably better ways to satisfy the need for a wall light than

The led strip came from my Christmas lights, as did the circuit - now transferred from breadboard to a more permanent soldered stripboard. The Arduino sketch, known as Dolores ("do lo-res") is all new, though, and parts of it (the bits that are plain C++ not Arduino code) are even unit-tested.

Perhaps worth noting

But now I can send it any picture I like. Here's a digital clock -

while sleep 2 ; do \
  ( convert -support .5 -depth 8 -fill red \
            -font DejaVu-Sans-Condensed -pointsize 7 -size 15x10! \
	    -draw "text 0,7 '$(date +%H%M)'" -sharpen 8 'xc:#333'  RGB:- | \
    tee out.rgb | \
    nix run nixos.mosquitto -c mosquitto_pub  -h mymqttserver.lan \
    	    		         -s --username username --pw password  \
				 -t effects/84F3EBE5E57C/image ) ; \
done

Beating the dead hobby horse I: structure, not strings#

Fri, 22 Jan 2021 21:04:32 +0000

In the domain of "how to write computer problems" (or "how to solve problems using computers" if you prefer a more user-centred framing) there are two things I bang on about endlessly. Today I'm going to write the first of them down.

Process structured values, not serializations

Your program interfaces with the outside world, and most likely it (unavoidably) sends and receives streams of bytes across that interface. Internally though, your program should not be processing those byte streams at anywhere but its boundaries. On input, to read them into structured values, and on output, to serialize those values back into bytes.

That sounds ... obvious, so - why do we so often get it wrong? Let's look at an example. Suppose you're writing a web application. You have some user-supplied content and you want to display it in the browser. You might (but shouldn't) do something like this:

def greet(name)
  puts "<html><head><title>Hi</title></head><body><h1>#{name}</h1></body></html>"
end  

What's wrong with this? Well, suppose the value of name is <blink>HAHA</blink> or </body> or <script>window.alert('pwned')</script> ... bad things happen. We need to "escape" that value before we print it, so that it does not contain syntax that will be treated as instructions to the browser's document parser.

It's reasonably straightforward to do so in that case, but now suppose that instead of replacing element content we want to replace an attribute value, or a class name, or a CSS style value or - oh my lord, the OWASP advice is hairy. Every time we have some variable content to interpolate into our template we need to figure out which context we're in and which rule or rules to apply. Whoever comes after us to review our code had better pay close attention too.

Is this the best we can do? No. Let me present to you another way of looking at this. In this perspective

Instead of interpolating our user content directly into the serialization as we write it out, it, we're going to build a document object with our user-supplied content and then only when we need to are we going to serialize the whole shebang.

def greet(name)
  doc = 
    [:html {}
      [:head {}
	[:title {} "Hi"]]
      [:body {}
	[:h1 {} [name]]]]
  # doc = transform_document_in_some_way(doc)
  serialize_to_html(doc)
end

We've decoupled the document generation from the serialization.

We still need to do the serialization, of course. We still need something that understands the encoding rules so that it may encode the document safely, but that "something" is library code, it knows the context for each node and it can do the correct escaping to print the content of that node.

This approach has other advantages, too - we have a tree structure, so we can do structural transformations by walking the tree. Maybe we need to add script nodes to the head so that we can add privacy=invading third party JS scripts. Maybe we need to put in a Covid19 banner at the top of the page. Maybe we need to find all the relative links on the page and add a prefix to their paths.

I concede that there are some circumstances - perhaps you're running on a microcontroller, you have huge amounts of HTML and no RAM in which to assemble a document - in which this approach is contraindicated, but to my mind these are special cases not default practices.

Not just HTML

Mistaking a serialized file format for an internal representation is by no means confined only to HTML. At the time I write this, 4/10 of the OWASP Top Ten have the common symptom "you tried to insert data into the serialized form of a structured value without paying really close attention to the rules of the encoding data, and your interpolated data itself contained serialised structure fragments, not just the flat value that you assumed". SQL injections, command injections, path traversal attacks. The commonly-touted remedies: use placeholders, use execve instead of system, use a Pathname or File class instead of a string where the "/" has special meaning.

At both ends

So don't serialize until you have to, but also can we talk about input? Deserialize (parse) what you get from the outside world soon as you humanly can, and certainly before you start trying to make decisions based on it. Get those strings and turn them into structured values before you start doing anything else to or with them.

This is not novel or original

I've been thinking in these terms for a long time, originally due to something Erik Naggum said:

the first tenet of information representation is that external and internal data formats are incommensurate concepts. there simply is no possible way they could be conflated conceptually. to move from external to internal representation, you have to go through a process of reading the data, and to move from internal to external representation, you have to go through a process of writing the data. these processes are non-trivial, programmatically, conceptually, and physically.

but more recently Language-theoretic security

LANGSEC posits that the only path to trustworthy software that takes untrusted inputs is treating all valid or expected inputs as a formal language, and the respective input-handling routines as a recognizer for that language. The recognition must be feasible, and the recognizer must match the language in required computation power.

and my favourite blog post of 2019, Parse, don't validate

The common theme between all these [ parsing ] libraries is that they sit on the boundary between your Haskell application and the external world. That world doesn’t speak in product and sum types, but in streams of bytes, so there’s no getting around a need to do some parsing. Doing that parsing up front, before acting on the data, can go a long way toward avoiding many classes of bugs, some of which might even be security vulnerabilities.

New Years Ruminations#

Fri, 01 Jan 2021 16:13:10 +0000

2021 will be, I assert confidently, the year I get NixWRT running on my internet gateway at home. A short list of the yaks I need to shave to get there, which you will note is a lot more concrete at the front end than the back: