Swift's native Clocks are inefficient
wadetregaskis.com
wadetregaskis.com
In C# native Stopwatch class is essentially all you need for simple timers with sub-millisecond precision.
Swift has not only the entire table of options from TFA to choose from, but also additional ones like DispatchTime [0]. They might all boil down to the same thing (mach_absolute_time, according to the article), but from the perspective of someone trying to learn the language, it's all a little confusing.
Especially since there's also hidden bottlenecks like the one this post is about.
[0]: https://developer.apple.com/documentation/dispatch/dispatcht...
I would also find it confusing if I found code doing something like network retries using `CACurrentMediaTime`.
for try await byte in bytes { ... }
for me reads like the time/delta is determined for every single byte received over the network. I.e. millions of times for megabytes sent. Isn't that a point for optimization or do I misunderstand the semantics of the code?[1] On x86 linux, it's just a quick call into the vdso that reads the TSC and some calibration data, dozen cycles or so.
But I imagine the time reading ones aren't as much optimized. People normally do not call them all the time.
At that point, even these slow methods are using about 0.5ms per million bytes, so it should be good up to gigabit speeds.
If that’s not fast enough, then sample every million bytes. Or, if the complexity is worth it, sample in an adaptive fashion.
again.
To mitigate this threat, javascript engine developers simply added a random fuzzy delay to all of the precision timing techniques. Swift's large volume of calls to unrequired methods is, almost certainly, Apple's implementation of this mitigation.
[1] https://en.wikipedia.org/wiki/Spectre_(security_vulnerabilit...
Also note you can get precise JavaScript measurements (and threading, eg. using pthreads and Emscripten) by adding some headers: https://developer.mozilla.org/en-US/docs/Web/API/Window/cros...
Though you can access these techniques now, in the weeks after Spectre attacks were discovered, the browsers all consolidated on "make timing less accurate across the board" as an immediate-term fix[1]. All browsers now give automatic access to imprecise timing by default, but have some technique to opt-in for near-precise timing.
Similarly, Swift has SuspendingClock and ContinuousClock, which you can use without informing Apple. Meanwhile mach_absolute_time & similarly precise timing methods require developers to disclose the reasons for its use before Apple will approve your app on the store[2].
[1] https://blog.mozilla.org/security/2018/01/03/mitigations-lan...
[2] https://developer.apple.com/documentation/kernel/1462446-mac...
Spectre mitigations also are really silly here because as a swift app you already have full access to all in-process memory. It would have to be about meltdown but meltdown is prevented through other techniques.
[1] https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
I'm pretty sure I can trigger a hit to the naughty API just by updating a @Published var in an ObservedObject. For those unfamiliar with SwiftUI, this is the most basic way to tell the system that your model data has changed and thus it needs to re-render the view. Pretty much every non-trivial SwiftUI app will need to do this.
It makes sense for a web browser. Not for something like Swift.
That's despite OSX having a vDSO style mechanism for it: https://github.com/opensource-apple/xnu/blob/master/libsysca...
And it’s a weird mitigation because Meltdown afaik has been mitigated on other OSes without banning high res timers.
The nail in the coffin is that it’s unlikely about security is Date and clock_get_time are accessible and an order of magnitude faster.
This seems a more likely scenario of poorly profiled abstraction layers adding features without measuring the performance.
A competent organization would not make the function call take longer by a random amount of time. You would just do it normally then add the random fudge factor to the normal result. That is not only more efficient, it also allows more fine-tuned control, the randomization is much more stable, and it is just plain easier to implement.
Though I guess I should not put it past them to do something incompetent given that they either implemented their native clocks poorly as the article says, or they incompetently implemented a Spectre mitigation as you theorize.
My two handy systems were an i5-1235U running 6.1.0-20-amd64 and a Ryzen 7 3700X also running 6.1.0-20-amd64. The fastest method was 3.7ns/s call on the i5 and 4ns/call on the Ryzen (REALTIME_COARSE and MONOTONIC_COARSE were about the same). If a "non-coarse" timestamp is required, the time increases to about 20ns/call on ryzen, 12ns on i5. (realtime, tai, monotonic, boottime).
On the i5, if I force the benchmark to run on an efficiency core with taskset, times increase to 6.4ns and 19ns.
% ./clocktest | rg MONOTONIC_COARSE
MONOTONIC_COARSE : 2.2ns percallMaybe someone knows why? On FreeBSD it is available [2].
[0]: https://www.manpagez.com/man/3/clock_gettime_nsec_np/ [2]: https://man.freebsd.org/cgi/man.cgi?query=clock_gettime
In FreeBSD, the distinction lives here: http://fxr.watson.org/fxr/source/kern/kern_time.c#L352
I can imagine that e.g. ContinuousClock is platform specific - any particular system may or may not be able to present a clock which exhibits change despite being asleep for a while and so to the extent Apple claim Swift isn't an Apple-only language, ContinuousClock might nevertheless have platform requirements.
But the protocol seems free from such a constraint. I can write this protocol for some arbitrary hardware which has no concept of time, I can't implement it, but I can easily write the protocol down, and yet here it is iOS 16.0+ anyway.
Maybe there's a separate view onto this documentation if you care about non-Apple platforms? Or maybe there's just an entirely different standard library for everybody else?
Also unixes let the sysadmin install additional libraries. How do I `apt install libswift2` on an iPhone?
much like libc, isn’t it? Apple writes tons of their own software in Swift and the number keeps going up. They’re trying to move more and more of the system to. It’s going to be loaded and in every system whether a user uses it or not.
No different from the objective-C runtime.
On Windows the equivalent would be MSVCRT which is sometimes shipped with the OS and sometimes not (depending on the versions involved). Sometimes you even need to worry about the CRT dependency with higher level languages because their “standard librairies” depend on the CRT.
So if you see that being installed with Java or C# or Unity, now you know why.
I expect that it's as simple as that: It's supported on iOS 16+ because it's dynamically linked by default, against a system-wide version of the standard library. You can probably try to statically link newer versions on old OS versions, or maybe ship a newer version of the standard library and dynamically link against that, but I have no idea how well those paths are supported.
0. https://github.com/apple/swift/blob/main/CHANGELOG.md
1. https://github.com/apple/swift-evolution/blob/main/proposals...
How can this API be used to fingerprint devices? It’s just getting the current time.
My best guess, you can infer a users time zone? Thus get a very general/broad area of where this user lives (USA vs EU; or US-EST vs US-PST)
Maybe I should just set my time to UTC on all devices
Timezones and such are one data point but the skews and accuracy and such are able to help you differentiate users too.
https://forums.whonix.org/t/javascript-time-fingerprinting/7...
I suspect the fingerprinting aspect is more indirect: mach_absolute_time is the most accurate way to measure small differences, so if you're trying to measure subtle differences in performance between different devices on some specific task, mach_absolute_time would be the way to go.
You can fingerprint a device using this because you know the wall clock difference and you know the previous cpu cycles. So you can assume any device with appropriately more cpu cycles may be the same device.
We’re talking measurements taken from different apps using Google or Facebook sdk.
And there’s the problem. Different devices have different uptimes. If you can get not only the uptime but a very very accurate version, you’ve got a very strong fingerprint.
If the service can learn the individual but current values of mach_absolute_time, then after a minimum of two requests you can likely compute N and distinguish between each device making a request.
This is possible because devices never reboot at exactly the same time.
https://github.com/bwbuchanan/absolute_time/blob/master/ext/...
https://rubygems.org/gems/absolute_time
Yes you want this in a development environment or perhaps in some sort of macOS app for developers, but probably not in most apps without a very specific and limited need.
In which case, it could be used as one of many signals in fingerprinting a device, as you could distinguish a returning user by checking their uptime against the time delta since the uptime at their last visit. It's not perfect, but when combined with other signals, might be helpful
Once you have a high-precision timer, there are all sorts of aspects of the user’s system you can fingerprint by measuring how long some particular API dependent on device performance and/or state takes to execute.
Platform vendors long ago figured out not to hand out the list of available fonts, but it’s a couple orders of magnitude harder to be sure switching some text from Menlo to Helvetica doesn’t leak a fractional bit of information via device-dependent timing.
EDIT: Others noted it’s actually ticks since startup, which is probably good for a few bits all on its own if you are tracking users in close to real time.
Why bother fingerprinting when you can just assign them an id and retrieve it later.
https://developer.apple.com/documentation/devicecheck
https://engineering.deptagency.com/securely-storing-data-on-...
https://developer.mozilla.org/en-US/docs/Web/API/Window/loca...
A fixed device ID survives even when an app is uninstalled and reinstalled and is the same for unaffiliated apps.
You can get the time zone from less naughty APIs, and that has way fewer bits of entropy.
I proposed something similar for Linux circa 2012. The patch got lost in some other unrelated discussion and I didn't pursue it.
struct timeval is a holdover from the 32 bit era. When everyone is using 64 bit machines, we should be able to get this data by reading one u64 from a shared page.
The table shows 19 or 30 milliseconds for Date / NSDate. Or am I misunderstanding something?
Instead of actually implementing security in the kernel they just kinda prevent you from distributing an app that may call that functionality. Because that way they can still let their buddies abuse it without appearing too biased (by e.g. having a whitelist on the device).
This technical failing probably, partially, explains why they are so against allowing sideloading. That, and they're scared of losing their cash cow of course.
Just squinting at the stack trace from the article, my intuition is that someone at Apple added a bunch of nice looking object-oriented stuff without regard for overhead. So a call to get a single integer from the kernel, namely the time, results in lots of objects being created on the heap and tons of "validation" going on. Then somebody on hacker news says this is all for your own good.
This occurred to me the other day. I've always laughed at the idea that Apple blocks sideloading for security purposes, but if the first line of defense is and always has been security through obscurity + manual App Store review (>= 2.0) on iOS, it's very possible that sideloading could cause problems. iOS didn't even have an App Store in release 1.0, meanwhile the Android security model has taken into account sideloaded apps since the very beginning [1]:
> Android is designed to be open. [...] Securing an open platform requires a strong security architecture and rigorous security programs. Android was designed with multilayered security that's flexible enough to support an open platform while still protecting all users of the platform.
[1] https://source.android.com/docs/security/overview
Edit: Language revised to clarify that I'm poking fun of the idea and not the one who believes it.
Apple's "security improvements" have always been about protecting their walled garden first and foremost.
- Stores their security credentials for critical sites (banks, HR/payroll, stores, govt services, etc.)
- Even if not, has unfettered access to their primary email account, which means it can autonomously initiate a password reset for nearly any site
- Is their primary 2FA mechanism, which means it can autonomously confirm a password reset for nearly any site
That's an immense amount of risk, both from apps running on the device, and from the device getting stolen. Both of the measures I mentioned are directly relevant to these kinds of threats. And, as I already said, Android has adopted these same security measures as well.
I've used android for years, never ran into any malware. I've also developed for android and ios. Writing malware is largely impossible due to the functional permission system, at least it's much, much harder than the other operating systems. Apple just pretends it's immune to malware because of the manual reviews and static analysis performed by the store. It's also why they're terrified of letting people ship their own interpreters like javascript engines.
One might argue that Android is targeted more than iPhone because of its larger userbase which certainly may contribute to it, but then MacOS which has a fraction of the userbase is more targeted than iOS - that makes the case that sideloading or lax app store reviews really are at least partly to blame.
Given much of the malware seems to be apps that trick users into granting permissions by masquerading as a legitimate app or pirated software, it's not really too hard to believe that Apple's app store with their draconian review process and no sideloading might be a more difficult target.
People deserve to be trusted with the responsibility of making a choice. We are allowing everyone to buy power tools that can cause severe injuries when mishandled. No one blinks an eye. Just like we allow that to happen, we should allow people to use their devices in the way that they desire. If this means some malware can exist then I consider this to be acceptable.
In the meantime system security can always be improved still.
Yet I still don't want to have to fix my mom's phone because its loaded with malware or worse, malware draining her bank account.
While iOS has longer device support, it's also way less modular and updates of system components will typically take longer to reach users than Android, so I'd say both have their issues there.
Counterpoint: tech websites have literally warned users that they need to be wary of installing apps from inside Google's walled garden.
> With malicious apps infiltrating Play on a regular, often weekly, basis, there’s currently little indication the malicious Android app scourge will be abated. That means it’s up to individual end users to steer clear of apps like Joker. The best advice is to be extremely conservative in the apps that get installed in the first place. A good guiding principle is to choose apps that serve a true purpose and, when possible, choose developers who are known entities. Installed apps that haven’t been used in the past month should be removed unless there’s a good reason to keep them around
https://arstechnica.com/information-technology/2020/09/joker...
"You should not trust apps from inside the walled garden" is not a sign of a superior security model.
This is not a counterpoint to what I was saying. I'm talking about sideloaded apps, not apps from Google Play. I agree that Google should work to improve their app vetting process, but that's a separate issue entirely, and one I'm not personally interested in.
This discussion seems to be headed in an ideological direction rather than a technical one, and I'm not very interested in that.
However, iOS makes the security trade off in the other direction.
All an app's executable code must go through the app vetting process, and additional executable code cannot be added to the app without the app going through the app vetting process all over again.
In contrast, Google has been unable to quash malware like Joker from inside the Play store because the malware gets downloaded and installed after the app makes it through the app vetting process and lands on a user's device.
> Known as Joker, this family of malicious apps has been attacking Android users since late 2016 and more recently has become one of the most common Android threats...
One of the keys to Joker’s success is its roundabout attack. The apps are knockoffs of legitimate apps and, when downloaded from Play or a different market, contain no malicious code other than a “dropper.” After a delay of hours or even days, the dropper, which is heavily obfuscated and contains just a few lines of code, downloads a malicious component and drops it into the app.
https://arstechnica.com/information-technology/2020/09/joker...
iOS not having constant issues with malware like Joker inside their app store has nothing to do with "security through obscurity" and everything to do with making a different set of trade offs when setting up the security model.
apple might pretend they are secure because they usually manage to catch such things during review. this doesn't actually mean they are secure.
end of the day, it's up to the user to choose what software they install, and what permissions they grant.
if your security model includes taking all user choice away, forbidding them from running software that they wish to run, and essentially treating them like unsophisticated toddlers that need your guidance because you know best, then sure, you might view this as a problem. but at that point, you are the problem.
The easiest way to see that Apple's security model is more robust is that tech websites don't have to warn users that they should fear the apps from inside the app store.
Regarding dynamic native code execution, please see saagarjha's comment and my reply.
> Apple's security model
It would be more accurate to say "the iOS security model", because as beeboobaa3 mentioned, macOS fully allows apps from outside the App Store, dynamic native code execution, and most other "insecure" things that are blocked on iOS.
15 Pro so definitely not an old phone new software issue.
Hundreds of nanos isn't great but it's certainly better than milliseconds.