Monday, September 24, 2018

R.I.P., Charles W. Moore, a fine man who liked fine Macs

A farewell and au revoir to a great gentleman in making the most of your old Mac, Charles W. Moore, who passed away at his home in rural Canada on September 16 after a long illness. Mr Moore was an early fan of TenFourFox, even back in the old bad Firefox 4 beta days, and he really made his famous Pismo PowerBook G3 systems work hard for it. Charles definitely was of the same mind I think a lot of our readers here are: "Even after going on a decade and a half, I still find them [his Pismos] a pleasure to use within the context of what they’re still good at." I'm sure most of us will agree the same is true for any classic computer in general and particularly Power Macs as a whole given how underwhelming Apple's current Mac offerings are. While later on he upgraded to a 17" Big Al, and although I admire the Pismo my favourite Mac laptop to this day remains the wonderfully customizable PowerBook 1400 (with a G3/466, thank you very much, and still looking for a solar cover!), I can think of few people who bore the standard of the classic Mac as a useful productivity device for as long as he did. Even old tools can still be the right tools when given the right job to do.

Go with God.

Friday, August 31, 2018

TenFourFox FPR9 available, and introducing Talospace

TenFourFox Feature Parity Release 9 final is now available (downloads, hashes, release notes). There are no changes from beta 3 except for outstanding security patches. Assuming no changes, it will go live Tuesday evening Pacific due to the US Labor Day holiday.

Allow me to also take the wraps off of Talospace, the new spin-off blog primarily oriented at the POWER9 Raptor Talos family of systems but will also be where I'll post general Power ISA and PowerPC items, refocusing this blog back to Power Macs specifically. Talospace is a combination of news bits, conjecture and original content "first person" items. For a period of time until it accumulates its own audience, I'll crosspost links here to seed original content (for the news pieces, you'll just have to read it or subscribe to the RSS feed).

As the first long-form article, read this two-part series on running Mac OS X under KVM-PPC (first part, second part). Upcoming: getting the damn Command key working "as you expect it" in Linux.

Sunday, August 26, 2018

TenFourFox FPR9b3 available

TenFourFox Feature Parity Release 9 beta 3 is now available (downloads, hashes, release notes). This version has site-specific workarounds for Github's sudden hostility to TenFourFox (fixed using the same workaround we use for Imgur) and pages that use the new version of Cloudflare RocketLoader (by essentially defeating it). I also reduced idle time deferral for a couple rare crashes on the test systems that seemed to be from low memory and added a little tuneup for HTML5 parsing from Firefox 55.

Of the security patches that landed in this version is a specific one for an issue that affects 10.5, but not 10.4. It's more of an information leak than anything else and wouldn't seem to be very common, but I was able to exploit it on the test network, so now it's worked around. Our implementation is completely different from Mozilla's largely for performance reasons since we only have two operating system flavours to worry about.

Watch for the final to emerge this weekend sometime, for public release next Tuesday (not Monday because of the US Labor Day holiday).

Tuesday, August 21, 2018

TenFourFox and legacy addons and their euthanasia thereof

Presently TenFourFox uses Mozilla Addons as a repository for "legacy" (I prefer "classic" or "can actually do stuff" or "doesn't suck") add-ons that remain compatible with Firefox 45, of which TenFourFox is a forked descendant. Mozilla has now announced these legacy addons will no longer be accessible in October. I don't know if this means that legacy-only addons will no longer be visible, or no longer searchable, or whether older compatible versions of current addons will also be no longer visible, or whatever, or whether everything is going to be deleted and HTH, HAND. The blog post doesn't say. Just assume you may not be able to access them anymore.

This end-of-support is obviously to correlate with the end-of-life of Firefox 52ESR, the last version to support legacy add-ons. That's logical, but it sucks, particularly for people who are stuck on 52ESR (Windows XP and Vista come to mind). Naturally, this also sucks for alternative branches such as Waterfox which split off before WebExtensions became mandatory, and the poor beleaguered remnants of SeaMonkey.

For TenFourFox users, there is an archive available from SourceForge of the last Firefox 45-compatible versions of popular addons, both classic and current. Naturally this archive is not comprehensive and won't ever be, though I'll consider adding other addons I believe are notable. Download and drop the XPI on any open browser window. Other users are welcome to grab stuff from our archives, but I consider 52-compatible versions out of scope, so please don't ask.

For OverbiteFF users, I will probably move it back over to Floodgap's gopher clients page and maintain it there, since if you have an interest in Gopher I can pretty accurately predict you probably don't use a vanilla stock web browser either. However, because OverbiteWX and OverbiteNX are fully compatible with WebExtensions, they will not be affected by this change.

Sunday, August 12, 2018

TenFourFox FPR9b2 available

TenFourFox Feature Parity Release 9 beta 2 is now available (downloads, hashes, release notes). This version tightens up the geometry on the date/time pickers a little, adds some more hosts to basic adblock, fixes a rare but easily wallpapered crash bug and further tunes up hash tables using a small patch from Firefox 63 (!). I am looking at a new JavaScript issue which does not appear to be a regression, but I'd like to fix it anyway since it may affect other sites. However, I'm not sure if this is going to make FPR9 final, which is still scheduled on or about September 4 due to the American Labor Day holiday on the usual Monday.

The WiFi fix in beta 1 was actually to improve HTML5 geolocation accuracy, and Chris T has confirmed that it does, so that's been updated in the release notes. Don't worry, you are always asked before your location is sent to a site.

On the Talos II side, I've written an enhancement to KVMPPC allowing it to actually monkeypatch Mac OS X with an optimized bcopy in the commpage. By avoiding the overhead of emulating dcbz's behaviour on 32-bit PPC, this hack improves the T2's Geekbench score by almost 200 points in Tiger. Combined with another small routine to turn dcba hints into nops so they don't cause instruction faults, this greatly reduces stalls and watchdog tickles when running Mac apps in QEMU. I'll have a formal article on that with source code for the grubby proletariat shortly, plus a big surprise launch of something I've been working on very soon. Watch this space.

Sunday, July 29, 2018

TenFourFox FPR9b1 available

Before we begin: if you haven't seen it, check out the newly updated and refurbished TenFourFox FAQ, and consider this sobering thought on the state of web monitoring advertising.

Also, for those of you who may be unaware, long-time Mozillian Gervase Markham passed away, surrounded by his family. He was ever a professional to the end. I didn't know him as well as some, but I'll always remember him, not least of which for his unwavering faith in the face of adversity and leaving us far too soon. Go with God.

TenFourFox Feature Parity Release 9 beta 1 is now available (downloads, hashes, release notes). There are several new features and many bug fixes in this version. FPR9 is also the first TenFourFox release to pull from the new extended support release, Firefox 60ESR, and we have updated the extended validation certificate roots and our certs'n'pins import script to pull from that source instead of the shortly-to-be-decommissioned 52ESR. All relevant security and stability patches on 60ESR so far have also been backported.

On the bug fix side, there is a crash fix for media tracks from Raphael, updates to the ATSUI font blacklist (mostly for certain Japanese fonts) that can now block incompatible fonts through the CSS Font Loading API as well, updated timezone data for the ICU internationalization library, ICU security fixes, fixes for button sensing in events which should get around some weird glitchy things where the mouse buttons get ignored, and a dumb old bug with WiFi scanning. I also added a layout fix for button subelements that keep getting split apart, fixing problems on sites like Twitch and GoDaddy.

There are also a number of performance related changes. First, the idle observer minimal interval has been increased to be a better fit for our old machines, since doing this every second (potentially) robs CPU time and possibly instruction cache space away from user interaction. Do note, however, that while this reduces work being run while you use the browser the work is only delayed and not eliminated, meaning improvements in responsiveness and animation will be at the cost of memory being occasionally held longer and taking longer to release, and possibly longer GC pauses (though less often), so advise if you don't think the tradeoff is worth it (this is adjustable, though it's hardcoded within TenFourFox and is not a pref). This release also has some tuning to Cocoa events handling to slightly reduce scroll wheel latency and reduce some overhead with custom events, and additional code in JavaScript to make it more nimble about cancelling and recompiling since most of our systems are uniprocessor.

The other big change is to array handling. I backported a number of changes that landed in Firefox 55 which increase the performance of certain array operations such as splices and shifts by anywhere from 35 to 80 times. This does not translate into as dramatic a boost as you might think because in small numbers these types of operations were already reasonably swift, nor are they typically executed in large numbers or in tight loops back to back, but for those sites that do, they will run quite a bit quicker.

Of the new features, CSS column properties are now unprefixed and tested, which will help improve site compatibility. Unfortunately one big new feature that I planned for FPR9 won't make this release: deferred idle callbacks. The requestIdleCallback DOM API was enabled in Firefox in Fx55 and allows browsers to schedule work in the idle time between animation frames. Rarely do any of our old systems have such idle time available, and the 50ms or less usually granted (and actually checked for by the W3C test suite) isn't much time to do much work anyway. However, we can also infer from the timeout that is (optionally) passed that the website is able to tolerate the work being deferred up to that long, so deferred idle callbacks deferred the work up to that long. For example, on YouTube this would delay comments and other pieces of the UI so that the CPU could concentrate more on decoding and blitting frames. My initial thought was to try to run the callback when the system was not under load, but it turned out to be simpler and more reliable to just run it at the maximum timeout interval (or after a default interval if one was not specified). Unfortunately, after a lot of idle callbacks had run test builds started suffering random stalls even after the callbacks had completed, indicating something wasn't getting cleaned up, so it is pref'ed off in this version while I try to figure out what I did wrong. You can play with it by turning tenfourfox.dom.requestIdleCallback.enabled to true, but you'll have to restart the browser if you change that setting, so remember that any assessment you make about performance should keep in mind whether the browser is "fresh" or not. This is something I want to get working but it's not a major issue right now because most of the sites that depend on it (including YouTube) have polyfills.

However, the other big new feature I wanted in FPR9 did land: native HTML5 time and date input controls. On my list of future features likely to be used by sites, these scored very high because for those sites that don't need custom clock/calendar UIs this can eliminate them having to load and maintain one of their own just to select intervals. Date and time input controls were not implemented in Firefox until Fx60, and the implementation Firefox uses is a cross-platform one with a fair bit of JavaScript and other support code for vagaries in date handling and localization. I really didn't want to backport all of that because it would be slower and bloatier and especially because we already have all of this special handling built into Mac OS X itself through NSDate. So I took a tip from the Android version and, in a like manner to the colour picker and file picker, which use native Cocoa widgets, implemented date and time pickers using the built-in NSDatePicker widget. This, in turn, handles all the calendar and date manipulations so we don't have to, displays the calendar and time and date using the user's own locale, and does it all at native speed to boot. Genius!

For simplicity I chose to implement this as a modal window rather than the drop-down Firefox 60 uses, which solved a lot of synchronization issues even though it's not as slick. Ordinarily you'd implement a simple modal window in Cocoa with an NSAlert, and if you want to add something to the alert box, you do so by creating an NSView with the widgets you want to splice in and inserting it as an accessory view.

There's just one problem: NSAlert didn't implement setAccessoryView: until 10.5, so you can't do that in Tiger. Or can you?

When looking for undocumented functionality in Cocoa, the best tools are either class-dump (3.1.2 works with Tiger), or my personal favourite GUI tool, MagicHat. Let's see what MagicHat comes up with for NSAlert:

// Framework:      AppKit
// Header:        NSAlert.h
// Documentation: Unknown

@interface NSAlert : NSObject
{
 int             _alertStyle;
 float           _buttonPadding;
 float           _buttonSpacing;
 float           _buttonSpacingMaxX;
 float           _buttonSpacingY;
 NSArray*        _buttons;
 NSSize          _defaultPanelSize;
 id              _delegate;
 SEL             _didDismissSelector;
 SEL             _didEndSelector;
 NSWindow*       _docWindow;
 id              _first;
 id              _helpAnchor;
 id              _helpButton;
 id              _imageView;
 NSTextField*    _informationField;
 id              _messageField;
 float           _messagePadding;
 NSSize          _minButtonSize;
 id              _modalDelegate;
 NSPanel*        _panel;
 id              _second;
 char            _showsHelp;
 id              _third;
 NSImage*        _unbadgedImage;
 char            _useNSLayout;
 [?]             reserved;
 id              reserved1;
 id              reserved2;
}
+ (id) alertWithError: (id) parameter1;
+ (id) alertWithMessageText: (id) parameter1 defaultButton: (id) parameter2 alternateButton: (id) parameter3 otherButton: (id) parameter4 informativeTextWithFormat: (id) parameter5;
+ (void) stopAllTimersForSpeaking;

- (char) _dontWarnAgain;
- (void) _setDontWarnMessage: (id) parameter1;
- (char) _showsDontWarnAgain;
- (id) addButtonWithTitle: (id) parameter1;
- (int) alertStyle;
- (void) beginSheetModalForWindow: (id) parameter1 modalDelegate: (id) parameter2 didEndSelector: (SEL) parameter3 contextInfo: (void*) parameter4;
- (id) buildAlertStyle: (int) parameter1 title: (id) parameter2 formattedMsg: (id) parameter3 first: (id) parameter4 second: (id) parameter5 third: (id) parameter6 oldStyle: (char) parameter7;
- (id) buildAlertStyle: (int) parameter1 title: (id) parameter2 message: (id) parameter3 first: (id) parameter4 second: (id) parameter5 third: (id) parameter6 oldStyle: (char) parameter7 args: (char*) parameter8;
- (id) buttonPressed: (id) parameter1;
- (id) buttons;
- (void) dealloc;
- (id) delegate;
- (void) didEndAlert: (id) parameter1 returnCode: (int) parameter2 contextInfo: (void*) parameter3;
- (void) didEndSheet: (id) parameter1 returnCode: (int) parameter2 contextInfo: (void*) parameter3;
- (void) finalize;
- (id) helpAnchor;
- (id) icon;
- (id) informativeText;
- (id) init;
- (id) messageText;
- (float) messageWidthForMessage: (id) parameter1;
- (void) placeButtons: (int) parameter1 firstWidth: (float) parameter2 secondWidth: (float) parameter3 thirdWidth: (float) parameter4;
- (void) prepare;
- (char) rememberChoice;
- (int) runModal;
- (int) runModalSheetForWindow: (id) parameter1;
- (void) setAlertStyle: (int) parameter1;
- (void) setDelegate: (id) parameter1;
- (void) setHelpAnchor: (id) parameter1;
- (void) setIcon: (id) parameter1;
- (void) setInformativeText: (id) parameter1;
- (id) setMessage: (id) parameter1;
- (void) setMessageText: (id) parameter1;
- (void) setRemberChoiceMessage: (id) parameter1;
- (void) setShowsHelp: (char) parameter1;
- (id) setTitle: (id) parameter1 andMessage: (id) parameter2;
- (char) showsHelp;
- (void) startSpeaking: (id) parameter1;
- (void) startTimerForSpeaking;
- (void) stopTimerForSpeaking;
- (id) window;
- (void) windowDidBecomeKey: (id) parameter1;

@end

Most of these are documented. Unfortunately there is no obvious analogue to setAccessoryView:, so there's no easy way that way. However, there is an interesting selector called buildAlertStyle:. This is not documented, but the name suggests that it gets called at some point to construct the NSAlert, presumably out of a generic NSWindow. Unfortunately because it's undocumented it's not at all clear what those parameters actually do.

I ruminated over this for a couple of days until by dumb luck I ran across an old library called NSAlertCheckbox. This library, though fragmentary and appearing to hail from around the days of Jaguar 10.2, does exactly what the name implies: it adds a checkbox control to an NSAlert. Well, said I, if it can add an NSButton, it can add a NSDatePicker. I cleaned up and expanded the library and wrote a little model (modal?) application to test my theory. It looked like this:

(Here is the source code for this example. You can compile it with Xcode 2.5 and the Mac OS X 10.4 SDK. Note in this and the below examples, because the model is being run from the command line and not within a regular NSApplication, it cannot intercept keystrokes. Just roll with this for the explanations below.)

The way the library works is by hooking those mysterious functions, which do indeed get called during window construction. Happily it turns out we don't need to know anything about what those opaque parameters are; we can modify the window without them (and just pass them along) by iterating through the components within the NSWindow that makes up the NSAlert. Once the code finds the second text field (the explanatory text, here articulately represented by the deep and meaningful words "Blah blah"), it then inserts a subview after that containing the date picker, et voilá.

This is not enough, however. While we can easily select the date and emit it (using NSDateFormatter), we can't type it, so selecting years and arbitrary months can sometimes require a lot of mousing around. Indeed, if you go to System Preferences to set the date and time, you have the choice of either using a stepper to manually enter a date or selecting one off the calendar. We can support that here too ... by adding another NSDatePicker!

(Source code for this example.)

The trick here was to keep them in sync so that you could type a date and have the calendar widget reflect it. By using a delegate on each date picker's cell, we can make modifications in one picker be synchronized to the other.

That suffices for dates. How about times? Straightforward enough: we just change the style to make the twin NSDatePickers into a clock and time stepper instead, and alter our template to NSDateFormatter to emit the time (in hours and minutes, and optionally seconds). Since the HTML spec also requires that we allow sites to specify minimums and maximums, let's implement that here too:

(Source code for this example.)

Because of the time interval constraint we implemented, when you run it you can only pick a time between 7:30am and 5:45pm; the pickers won't let you select anything else. Exactly what we want.

Before you upgrade to the beta, open either the MDN time or date picker pages and click in one of the demonstration input fields. In FPR8, this is just a text box, and you just enter text. (Same for Safari.) In FPR9, however, when you click or select that field the appropriate picker will pop open and the field will be autofilled for you in the proper format. If you press delete in the field, the date or time will be cleared. If you click Cancel, no change will occur. All of the standard constraints are supported, along with defaults (if no default is specified, the current time and/or date is used). Easy. As a safety measure, though, I implemented a basic filter to prevent NSDateFormatter from being exposed directly to web content since who knows what crap is lurking in there; it's only used as a secondary validator once the web-provided date is known to be in a non-pathological format.

Still to be implemented are month (easily done by just returning the month, not the full date), local date and time (needing a quadruple date picker) and week (harder, but possible). With the exception of local date'n'time, however, these are much less likely to be common and I'll defer those to later versions of the browser.

FPR9 will come out officially parallel to Firefox 62 and 60.2 on September 4, but I wanted a nice long beta test period since there is a lot of stuff in this release and to provide a sufficient timeframe for additional betas if required, so you're getting what I've got now. Bang on it and post your impressions in the comments.

Thursday, July 26, 2018

NetSpectre: not much of a PowerPC threat either

In the continuing death march of Spectre side-channel variants for stealing data, all of the known attacks thus far have relied upon code running locally on the computer (so don't run sketchy programs, which have much better ways of pwning your Power Mac than slow and only occasionally successful data leaks). As you'll recall, it is possible for Spectre to succeed on the G5 and 7450 G4e, but not on the G3 and 7400.

The next generation is making Spectre go remote, and while long hypothesized it was never demonstrated until the newest, uh, "advance" called NetSpectre (PDF). The current iteration comes in two forms.

The first and more conventional version is like Spectre in that it relies on CPU cache timing. A victim application would have to have something called a "leak gadget," similar to the one in Spectre where network-facing code processes some network packet with a condition that's usually true and sets a flag based on a data bit of interest in memory. The processor, after enough training by the attacker, then is induced to mispredict, which means the flag is now in the cache even though it never observably changed. This could be done as with the example in the paper, where an attacker sends packets with multiple normal bitstream lengths, training the predictor, and then suddenly sends one with an abnormal or out-of-bound one. The flag isn't actually set, but the misprediction caused it to be loaded into the CPU cache. Later on, the application executes a "transmit gadget" that uses that flag to do a network-observable operation. The flag is in the cache, so the transmit gadget runs just a little bit faster, and the attacker can infer that data bit.

This sounds very slow and error-prone, and it is. In fact, it would be even worse on our slower systems: besides the fact that it presupposes the machine is vulnerable to Spectre in the first place (G3 and 7400 systems don't seem to be), we would generate packets much slower than a modern system, meaning the attacker would have to wait even longer to differentiate a response and the difference between the flag being and not being in the cache is likely to be drowned out by the other code that needs to execute to generate a network response. Looking at the histogram for the ARM core they tested, which is more comparable to the PowerPC than an Intel CPU, there is substantial overlap between the '1' and '0'; if network latency intervenes, it could take literally millions of measurements to extract even a single bit. And that's assuming the attacker knows enough about the innards of your network-facing application (like TenFourFox, or what have you) to even know the memory location they're looking for. Even with that sizeable advantage, even when attacking a far faster computer over a local network, it took 30 minutes for the researchers to exfiltrate just a single byte of data. Under the most optimal conditions for such an attack, a Quad G5 would probably require several times longer; a 7450 would take longer still.

The researchers, however, recognized this and looked for other kinds of network-observable side channels that could be faster to work with than the CPU cache. The vast majority of modern CPUs these days have some sort of SIMD instruction set for working on big chunks of data at once. We have the 128-bit AltiVec (VMX) in Power Mac land on G4s and G5s, for example, and later Power ISA chips like the POWER9 have an extension called VSX; Intel for its part historically offered MMX and the SSE series of instructions all the way up to things like AVX2. AltiVec and VSX are pretty well-designed and reasonably power-efficient extensions but only work on 128 bits of data at once, whereas AVX2 was extended to 256 (AVX-512 even supports 512-bit registers). Intel's larger SIMD implementations require more power to run and the processor actually turns off the circuitry operating on the upper 128 bits of its AVX vector registers when they aren't needed. With that crucial bit of knowledge you can probably write the end of this paragraph already, but turning on the upper 128 bits is not instantaneous and can incur a noticeable penalty on execution if the upper bits aren't already activated. If you can get the processor to speculatively execute an AVX2 instruction operating on the upper bits based on the data bit of interest, you can then infer from how quickly that instruction executed what the data bit was, the execution time itself inferred from a later network-visible operation that also uses the AVX2 upper unit. The AVX2 upper unit cycles on and off with roughly a 1ms latency, an eternity in computing, but it requires very few network measurements to distinguish bits and reduces the time to exfiltrate a byte to around 8 minutes in the paper.

No PowerPC chip used in any Power Mac behaves in this fashion, even with AltiVec instructions. The G3 doesn't have AltiVec (duh), and the AltiVec units in the 7400/G5 (they use similar designs) and the 7450 are always active. AltiVec instructions weren't implemented on "big POWER" until the POWER6, and even for the POWER6 through POWER9, I can't find anything in IBM's technical documentation that says any chip-internal functional unit, whether FPU, LSU, vector unit or otherwise, is dynamically powered down when not in use.

I think we've got bigger things to worry about than this.