Archive for September 14, 2015

Monday, September 14, 2015

Subscription iPhones

Benedict Evans:

However, a big shift in the mobile business in the last few years has been to unbundle the ‘subsidy’ from the contract into a separate installment plan, making the price much more transparent to the user. There was a widespread narrative that this would damage the high-end of the market (partly Samsung but mostly Apple), but this doesn’t seem to have happened at all.

However, shifting to an installment plan model does introduce a couple of interesting new dynamics.

First, unbundling the installments from the contract has often meant that the upfront cost of the phone goes away. Instead of paying (in the USA) $200 up front for a new iPhone, you pay zero. All things being equal, the monthly payments are therefore higher than the old subsidy that was embedded in the monthly phone contract, but it’s now two separate fees, the service part is now cheaper and the increased monthly installment/subsidy element is directly linked to ‘get a cool phone for zero up front’, so it may be easier to swallow.


So what happens to the old phones? When you take that upgrade, you have to hand in your old one. They go into the secondary market, which is rather the dark matter of the industry - we know it must be large and we can get some sense of that from survey data, but we don’t have a solid number. One illuminating data point is the fact that for the last several years the number of iPhones that seem to be in China (if you look at data from companies like Baidu) has been rather larger than the number of iPhones that Apple’s financial reporting implies could have been sold there. Second-hand closes some of the gap.


The really golden conversion is someone who was buying a new phone every two years (and probably not selling the old one). Now, instead of $650 over 2 years for the base model, they pay $778 and the previous years’ phones can be sold for another (say) 2x$350.

System Integrity Protection Documentation and Bugs

System Integrity Protection Guide (PDF):

This document covers the key concepts of System Integrity Protection and explains the implications it has on the design and capabilities of apps.

Via Rich Trouton (tweet), who has filed two bugs:

SIP’s protection of /System affects XProtect’s XProtect.plist and XProtect.meta.plist configuration files as they are stored in the following location inside /System:


As the XProtect configuration files will be locked against editing on OS X El Capitan, this means that they can no longer be managed to allow older versions of the Flash and Java browser plug-ins to run.

Pike has posted the man page for the new csrutil configuration tool. The “status” command lets you programmatically detect whether System Integrity Protection is enabled.


Note: To safeguard against disabling System Integrity Protection by modifying security configuration from another OS, the startup disk can no longer be set programmatically, such as by invoking the bless(8) command.

Previously: System Integrity Protection (a.k.a. Rootless).

Update (2015-09-22): Rich Trouton:

This allows SIP’s configuration to persist across OS installs, but this design choice also means that resetting NVRAM will cause SIP to reset as well. In my testing, this reset will result in the following SIP configuration:

Update (2015-10-07): Gus Mueller:

“Message from debugger: cannot attach to process due to System Integrity Protection”. So much for debugging Automator actions in 10.11.

Update (2015-10-08): Rich Trouton:

To see which files have been protected by SIP, use the ls command with the capital O flag in Terminal[…]


SIP’s protections are not limited to protecting the system from filesystem changes. There are also system calls which are now restricted in their functionality.

  • task_for_pid() / processor_set_tasks() fail with EPERM
  • Mach special ports are reset on exec(2)
  • dyld environment variables are ignored
  • DTrace probes unavailable


It is also possible to enable SIP protections and selectively disable aspects of it, by adding one or more flags to the csrutil enable command. All require being booted from Recovery in order to set them[…]

Problems With iOS’s Flat Design

Amy Hoy:

But a little faux leather isn’t the problem. The problem is deeper:

  • misusing metaphors (e.g. turning buttons into links)
  • eliminating the only affordances that software can have — visual affordances
  • using fake physical metaphors for interactions, such as using “wheels” for data entry
  • eliminating information hierarchy – homogenizing spacing and typography, for “visual tidiness”
  • giving all types of interface widgets the same visual appearance
  • reusing the same interaction design for click UIs (on 13″-27″ screens) and touch UIs (on 5″ screens)
  • tiny tap or click targets with invisible boundaries
  • software and icons that all look the same

And these mistakes are especially galling because they’re exactly the kind of thing that Apple themselves used to rail against.

Nick Heer:

Here’s the thing: the Apple that Hoy describes hasn’t existed for a very, very long time. Beginning around the introduction of OS X, Apple stopped following the HIG so strictly and started experimenting.


I include these examples not to say that Hoy is wrong in her criticisms of recent iOS interface design, but to point out that the HIG was something that was frequently about aesthetics and trends. iTunes 5’s UI wasn’t a smooth grey because of research and interaction; it was because brushed metal stopped being trendy and started to look kind of, uh, bad. “Unified” windows in Tiger did not have a consistent use-case defined by the HIG, either.


The problems with iOS’ UI aren’t because it doesn’t follow the HIG. It rewrote the HIG, establishing even greater consistency between apps.

Learning Lessons The Hard Way

Code Climate:

Around this time we began a process of re-running old analyses that had failed, and were able to reproduce the issue. This was a critical learning, because it refuted the theory that the issue was ephemeral. With this information, we took a closer look at the objects in the analysis-level cache. We discovered that these marshaled Ruby objects did not in fact hold a reference to the contents of files as we originally believed. Problematically, the object held a reference to the Git service URL to use for remote procedure calls.

When a repository was migrated, this cache key was untouched. This outdated reference led to cat-file calls being issued to the old server instead of the new server. Ironically, we’ve now determined that since the cached Ruby objects did not include the Git blob data, it never generated a performance benefit of any kind. Significantly contributing to the difficulty of debugging this issue, the library we use to read Git repositories in our git service returns empty strings if the repository directory does not exist on disk, rather than an exception. Armed with a root cause -- caches containing invalid service URLs -- we discovered one other call site that could exhibit similar problematic behavior.

Via Soroush Khanlou:

The everpresent joke in computer science says there’s two hard problems: naming and cache invalidation. When I was starting out, I remember thinking “ha ha, there’s no way cache invalidation could be that hard”. Fast forward a few years, and while I’ve learned a few lessons of my own about bad caches, reading Code Climate’s incident report for a major issue made me understand on a far deeper level what it means for cache invalidation to be hard. Lesson learned, bon mot deployed.

Backdooring JavaScript Using Minifier Bugs

Yan Zhu (via Hacker News):

The coolest article I’ve read so far in it is “Deniable Backdoors Using Compiler Bugs,” in which the authors abused a pre-existing bug in CLANG to create a backdoored version of sudo that allowed any user to gain root access. […] That got me thinking about whether you could use the same backdoor technique on javascript. JS runs pretty much everywhere these days (browsers, servers, arduinos and robots, maybe even cars someday) but it’s an interpreted language, not compiled. However, it’s quite common to minify and optimize JS to reduce file size and improve performance. Perhaps that gives us enough room to insert a backdoor by abusing a JS minifier.


So if we can trick the minifier into erroneously applying De Morgan’s law, we can make the program behave differently before and after minification! Turns out it’s not too hard to trick UglifyJS 2.4.23 into doing this, since it will always use the rewritten expression if it is shorter than the original. (UglifyJS 2.4.24 patches this by making sure that subexpressions are boolean before attempting to rewrite.)


The backdoor examples that I’ve illustrated are pretty contrived, but the fact that they can exist at all should probably worry JS developers. Although JS minifiers are not nearly as complex or important as C++ compilers, they have power over a lot of the code that ends up running on the web.