
A photo is crashing some Android phones - pseudolus
https://www.bbc.com/news/technology-52891650
======
McDev
Curiosity (stupidity?) got the better of me and I ended up awake until 2am
fixing this last night on my Pixel 3a.

I was fortunate enough to have developer mode & USB debugging enabled, which
allowed me to install some code to clear the wallpaper using the
WallpaperManager [0].

Sadly it wasn't as simple as pushing the code to the phone and running a
command to execute it. When the device boots, it would crash _almost_
instantly and reboot into recovery mode after attempting to show the wallpaper
a few times. This meant I couldn't put my passcode in, which meant Android
refused to run the application I made to clear the wallpaper.

The ADB (Android Debug Bridge) tool [1] lets you replicate user input for the
connected device, so you can basically swipe the screen / enter keys from the
command line. I was able to use ADB to swipe up on the lock screen and enter
my passcode. This was a start but wasn't enough, as the crash was happening
before the wallpaper deleting app could be started.

I figured the unlock process was taking too much time, and found out after
Android 8 (Oreo) you can actually use ADB to change or remove your passcode
[2], provided you know your existing passcode. After I removed my passcode I
was able to reboot the device, and run a single ADB command to swipe up on the
screen and delete that cursed wallpaper.

And no it wasn't worth it, but I enjoyed the challenge

[0].
[https://developer.android.com/reference/android/app/Wallpape...](https://developer.android.com/reference/android/app/WallpaperManager)

[1]. [https://developer.android.com/studio/command-
line/adb](https://developer.android.com/studio/command-line/adb)

[2].
[https://android.stackexchange.com/a/194779](https://android.stackexchange.com/a/194779)

~~~
dcow
Times like this are why it would be really nice for google to allow a root
shell for developers when booted in recovery mode or something. Trying to fix
this from userspace in the short window you have before the systemui
crashes... what a silly avoidable nightmare.

~~~
zozbot234
You can root your phone, but then you lose SafetyNet which means that things
like banking apps, etc. won't work. For "normal" developer access there's adb
which does have some special privileges (nowhere close to actual root, but
better than nothing), but using it to change screen background settings would
be quite clunky. Even using the adb shell to delete the file would run into
restrictions on general storage access that newer Androids have.

~~~
ars
Magisk has an option to force enable passing SafetyNet, plus hide Magisk. If
you combine those you can have root and still run banking apps and Google Pay
like normal.

[https://www.didgeridoohan.com/magisk/MagiskHideSafetyNet](https://www.didgeridoohan.com/magisk/MagiskHideSafetyNet)

~~~
zozbot234
Magisk Hide is an unreliable workaround, since remote attestation of the
running OS could be required at any time to pass SafetyNet. Even the author of
Magisk Hide is well aware of this.

~~~
tetris11
Could you explain that more, I didn't understand your response

~~~
power78
See this tweet chain from the Magisk author. It seems Google might enable
remote attestation at some point like they did for a short period during this
tweet, defeating MagiskHide.

[https://twitter.com/topjohnwu/status/1245956080779198464?s=1...](https://twitter.com/topjohnwu/status/1245956080779198464?s=19)

------
mtklein
I wrote a lot of the Skia color management code involved here, and I think
maybe I can clear some things up? I'd be happy to answer any questions you
might have, either here or on
[https://bugs.chromium.org/p/skia/issues/detail?id=10301](https://bugs.chromium.org/p/skia/issues/detail?id=10301)
where we've been trying to think about how much Skia's involved with the root
cause of this bug.

There's no "Skia color profile" per se. When Skia's asked to write a JPEG from
a pixel buffer tagged with a color profile (SkColorSpace), we auto-generate an
ICC profile programatically from the parameters that describe the color gamut
and transfer functions we use to represent those color profiles. That's what
the code in this file is up to:
[https://source.chromium.org/chromium/chromium/src/+/master:t...](https://source.chromium.org/chromium/chromium/src/+/master:third_party/skia/src/core/SkICC.cpp)

So this profile is one of infinite possible profiles that'll have
"Google/Skia/..big long MD5.." somewhere in them.

This profile in particular looks like it's probably describing the ProPhoto
color space, which is very, very large and uses imaginary colors outside
visible light to increase its gamut. While the JPEG itself is always storing
values in range in the ProPhoto gamut, when you convert that to another gamut
(say, to match the display, or to sRGB) it's very easy to end up with logical
color channel values less than zero or greater than one, which do make a kind
of sense, but not to code that expects colors are always sRGB bytes.

It's unclear to me what gamut the colors being read in that Java code are in,
and that'd very much affect what the appropriate values for that
LUMINOSITY_MATRIX should be. Those are the correct values to get the
luminosity for sRGB colors (though I think what's being calculated here is
subtly-different gamma-encoded "luma" instead), but they're not likely a sound
way to get luminosity if the image is in any different gamut. A typical
strategy is to convert any image you load to the display gamut early, since
you'll need to do that eventually to display it. And it's more and more common
that phone display gamuts are not sRGB, usually something wider now like
Display P3.

~~~
wereHamster
From the Skia bug report:

> out of bounds write in Java

Isn't Java supposed to be a language safe from these kinds of bugs? At the
very worst it throws an exception, which should be caught and dealt with
accordingly… How can that crash the whole phone?

~~~
ken
Every time there's a new programming language which claims to be "safer" than
existing ones, I look at what they do differently. In some cases, they've come
up with a new way to restrict computation so that undefined/error cases aren't
possible. In many cases, though, their solution is more along the lines of
"don't do that", often with syntax that discourages (but doesn't forbid) it.

The trouble is that it's really easy to say "access the 10th position in a
5-element array". It's possible to make a programming language that doesn't
allow you to say this, but it either makes it really awkward to do anything
with arrays, or simply pushes the error somewhere else -- or both.

~~~
petters
Well, if this process had been written in C, this may have been a security
issue, so Java is still an improvement.

~~~
lovasoa
Being able to deny a victim access to their phone just by having them set a
given wallpaper definitely IS already a security issue.

~~~
petters
OK, fair enough. But you know what I meant. :-)

------
Someone
_“Restarting the device in safe mode (by holding down the volume button during
boot-up) did not fix the issue.”_

So, lesson learned: in safe mode, do not use a background image that the user
set.

~~~
organsnyder
Ha. Perhaps I'm misremembering, but I think I remember this behavior (not
using the user background in safe mode) back in Windows 95.

~~~
eldelshell
It also removed the IE thing which showed icons or some stuff like that...
Wait, that was in 98.

~~~
throwanem
Active Desktop.
[https://en.wikipedia.org/wiki/Active_Desktop](https://en.wikipedia.org/wiki/Active_Desktop)

~~~
decko
Was that the feature that would occasionally replace your desktop background
with an error message?

------
AdmiralAsshat
Granted we understand "brick" to mean the device cannot boot, but this comes
pretty damn close on some phones, it seems.

> "After setting the image in question as a wallpaper, the phone immediately
> crashed. It attempted to reboot, but the screen would constantly turn on and
> off, making it impossible to pass the security screen," he noted.

> Restarting the device in safe mode (by holding down the volume button during
> boot-up) did not fix the issue."

If restarting doesn't fix it, and not even safe mode will allow you to change
the wallpaper to get around it, what method of recovery is left for the
affected user? Factory reset from recovery mode?

~~~
zozbot234
It depends. If the bootloader is unlocked, they could boot a custom recovery
and alter the system image to try and insert a workaround (such as deleting
the buggy library and dealing with the resulting breakage). If the data
partition is fully unencrypted, they can even delete the offending file
straight from recovery. On a bootloader-locked, fully encrypted device (the
default nowadays) they'd be SOL and have to use the stock recovery or
bootloader to force a factory reset - not only would that involve obvious data
loss, but they would even have to deal with FRP afterwards.

~~~
f1refly
You can also delete the offending file with a fully encrypted main storage,
since twrp supports decrypting and mounting the storage on demand.

~~~
zozbot234
> since twrp supports decrypting and mounting the storage on demand.

It advertises that support, but I've never really seen it work. It seems that
modern FDE on Android is such that you can only really "decrypt" from the
system environment itself, not from different code - and it's not clear how to
fix this.

~~~
gruez
>It advertises that support, but I've never really seen it work

works for me. it really depends on whether your TWRP distribution implemented
it properly. AFAIK android phones don't have a mechanism to bind encryption
keys to a system state (similar to sealing keys to PCRs for TPMs on PCs), so I
don't think your theory is correct.

------
gruez
Relevant code in AOSP:
[https://android.googlesource.com/platform/frameworks/base/+/...](https://android.googlesource.com/platform/frameworks/base/+/refs/tags/android-10.0.0_r35/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java#134)

~~~
zelos
And the comment in Color.java:

    
    
      * @return A float value with a range defined by the specified color's color space

~~~
jeffbee
Using the sum of three floats to index an array?

~~~
Zenbit_UX
What could go wrong!

~~~
jeffbee
It looks like this comment is not right. There is:

    
    
      public static int blue (int color)
    

Anyway this thing has range [0, 255] and adding three of them together as an
index of an int[256] doesn't seem like it would ever work regardless of the
colorspace.

~~~
mtklein
Red, green, and blue have been scaled by .2126, .7152, and .0722, which add up
to 1.0 exactly (even in single-precision float), and if those values really
were all in [0,255] range, the maximum value that could be produced by this
math is only 254, due to rounding.

I think what's happening here is that the image is in a format that's holding
those original red, green, and blue values in a format that can hold values
outside logical [0,1].

Update: sorry, the comment below me doesn't seem to have a 'respond' link so
I'll just edit one in here. I totally agree with you it's good practice to
document your invariants in code, but in practice it would result in the same
thing... an unhandled failure with nothing better to do than crash the
process. In a way (if you squint) indexing into an array of size 256 is itself
documenting the invariant that the index is less than 256. It's just that the
invariant itself is wrong.

~~~
jeffbee
On my planet we write those invariants in code, such as

    
    
      CHECK(Color.red(pixel) < 55);
    

Or whatever.

~~~
gruez
You mean an assertion? I'm not sure how that would help. The code is still
going to crash, and unless you tested for that specific case, it's not going
to show up in testing either.

------
jasona99
I actually looked into this when I saw it in the original tweet. I tried with
a current Android 10 emulator, crashed SystemUI. Tried with the latest build
of AOSP, was a-ok. Whatever the issue was, looks like it got resolved already
in either the Android color library or the ImageProcessHelper for the
wallpaper (the piece of code that was initially crashing with an out of bounds
error). I haven't spent much time looking into exactly when/where it was
fixed, though.

Quick edit to add that, despite this, I do not believe those changes have made
their way into most devices. It seems the error stemmed from the possibility
of returning a value over 255 when a histogram was calculated from the
addition of color values. As stated in the article, this seemed to result from
the use of the Skia color profile in particular. I do not know about other
color profiles. The code mentioned by gruez was what I got when the emulator
was crashing.

~~~
wheelie_boy
This could explain why it might not have shown up in testing.

It's not just that the image had a non-sRGB colorspace, it's also that the
pixel values in this specific image were out of the expected range.

~~~
jfkebwjsbx
"Out of expected range" values should be the very first thing to test for...

~~~
OJFord
And maybe it was; maybe the colour space aspect also was.

Testing combinations of edges is not so common/obvious.

------
hdjriro
Opening the picture in Windows Photo Viewer (the old on introduced in Windows
7) throws this error: "Windows Photo Viewer can't display this picture because
there might not be enough memory available on your computer."

Other Windows included apps, like Paint, Paint3D and Photos open it just fine.

~~~
DudeInBasement
Paint is like the Notepad of Artwork apps. It can handle anything.

If notepad doesn't open it, nothing will.

------
MaxChinni
Citing a comment I can find anymore:

    
    
      For everyone who tried it and wants to recover phone without clean wipe. remove these files (I did it with twrp)
    
      /data/system/users/USER_ID/wallpaper_info.xml
      /data/system/users/USER_ID/wallpaper_orig
      /data/system/users/USER_ID/wallpaper
    
      it resets your wallpaper to default one

------
sp332
According to the linked theory from @evowizz, _any_ photo with an unsupported
colorspace would cause this issue. Seems like someone would have noticed
before? Maybe in QA or at least during a beta instead of 9 months after
launch?

~~~
panpanna
What you see right now is the normal Google QA process.

They have literally billions of beta testers, who are even paying for the
privilege.

------
matchbok
The lack of quality control in the Android SDK is pretty impressive. It is by
far the worst SDK I've ever used. Hell, even simple think like hiding/showing
a keyboard requires a ton of code and checks. In 2020.

~~~
enos_feedler
It is out of control.

I actually think between the HAL layer, OEMs, chipsets and 3P ecosystem it is
very difficult to dig out of the hole that Android has built. Too much was put
into short term thinking on annual releases and gap closing with Apple. While
Apple planned APIs years out for end to end products, Android had to blindly
copy APIs and everything is far less elegant. Android isn't working. It isn't
capturing the smartwatch ecosystem well (Fitbit) and it isn't capturing the TV
ecosystem well (Roku).

The net impact is harmful to developers. We don't get the reach and
compatibility we were promised. We have very fragmented ecosystem to develop
for. We have specific device SDKs we have to use to tap into novel hardware. I
can't complain enough.

Android had a huge opportunity to define the next evolution of compute
platforms on top of the linux kernel and it has kind of blown it.

I think there are even signs Google leadership sees this and is investing in a
portfolio of strategies such as CameraX, Pixel, Flutter/Fuschia.

With the Huawei situation too, I think the general health of the Android
ecosystem is some of the worst it has been. Globally I think we are going to
see even more fragmentation.

We need something that ties this all together. It's not going to be a full
blown OS layer, but something to manage the madness for 3P devs.

~~~
pjmlp
I find so tragic that Android is worse than J2ME in regards to fragmentation,
worse than Symbian/iOS/Windows/Maemo/Jolla in C++ support, at every Google IO
we get the best practices rebooted.

Oboe and Vulkan are very good examples how clunky everything is.

Here we have two API that are supposed to be relevant for the platform (real
time audio C++ framework) and next generation 3D API support, for which we get
told to clone github repos, compile everything from scratch and do the
integration with the applications ourselves.

Comparing this with iOS SDK and XCode templates is just feels like having to
nuke it all.

I have been moving away from NDK to WebGL 2.0 / WebAssembly, as it is good
enough for my interactive demos and Chrome team at least seems to be a bit
more sane.

~~~
jstimpfle
I've made some WebGL/WASM experiments, too - getting my UI and 3D to the
browser. Any references for running this on Android smartphones? (I want to
make an app, not a website)

~~~
enos_feedler
WebGL/WASM sounds like a good approach to solve fragmentation. Things will get
even better once WebGPU is supported as a Vulkan substitute.

~~~
pjmlp
The irony of WebGPU, is that we will be able to get it via Chrome and
frameworks like BabylonJS, while the Android team is not willing to provide
something similar to Java/Kotlin devs.

Sceneform seems to be dead, and Filament is nothing more than a tech demo.

------
TazeTSchnitzel
Remember those iOS text handling bugs? Fun.

------
dheera
I wonder whether it would be a bad idea to have a "dev" mode where exceptions
are thrown and a "production" mode of compilation where every single statement
is wrapped in a try-catch block with a default behavior. For example:

    
    
        histogram = getHistogram();
    

should be wrapped automatically in:

    
    
        try { histogram = getHistogram(); }
        catch(Exception e) { console.log(e.toString()); histogram = DEFAULT_HISTOGRAM; }
    

Something like:

    
    
        y = a / b;
    

should be wrapped in:

    
    
        try { y = a/b; }
        catch(Exception e) { console.log(e.toString()); y = 1e999; }
    

Wrap every function call like this, and just don't let Java exceptions bring
down an entire system in production especially when a lot of the time it's
just a petty UI issue.

Obviously never do it in development though. But odd UI behavior instead of
crashes might make a bunch more users happy which is ultimately what matters.

~~~
nicoburns
It seems that all you'd need is a single try-catch around the high-level
operation. I inherited a system where all the errors were swallowed and it was
a nightmare. If something failed it was impossible to tell why.

~~~
dheera
Yeah, I agree that the developer shouldn't do that in the source code. I'm
more thinking of a compilation mode where the system tries to consistently do
something just _slightly_ smarter than give up when there is an exception, and
that is strictly only for production use.

A divide by zero error on a button's width shouldn't cause a spacecraft to
give up and abort its mission to the moon. That wouldn't happen, but it's just
a figurative description of what I would like. It's ridiculous for an OS to go
into a boot loop because of a color histogram. A better behavior would be for
the background to be set to an array of NaNs, and the background renderer to
fail gracefully to a plain black or white background.

------
surround
Another article, which includes the wallpaper in question and the reason why
it crashes the phone.

[https://techxplore.com/news/2020-06-wallpaper-image-
android....](https://techxplore.com/news/2020-06-wallpaper-image-android.html)

------
cristaloleg
One more argument why do we need more (and more) fuzzing on a regular basis.

Basically everything where we can pass some specially encoded date (read as
format or protocol) can be made with bugs and edge cases not covered by test
or by intent look (how to say it properly in English? :)

So yeah, fuzzing.

------
m3at
Tangentially related but that might interest fellow readers, you have multiple
ways to make a valid image crash a device, one example being making a png bomb
[1]. This is similar to a zip bomb, the file will by expanded to order of
magnitude more bytes than its compressed size when opened, which might throw
an oom error or fill up the disk quickly.

[1] [http://www.aerasec.de/security/advisories/decompression-
bomb...](http://www.aerasec.de/security/advisories/decompression-bomb-
vulnerability.html)

------
unexaminedlife
Admittedly I haven't been following this story, but now that I see it on HN,
am genuinely curious whether they were able to rule out that hardware is
involved?

Also curious to know if perhaps there are flaws in the image format's spec
that are being exploited?

------
ganstyles
Oh wow, I set this on my Pixel 3 and started immediately flashing on and off.
It reset and allowed me to do a factory reset, and now it works. That’s crazy,
don’t do this.

To be clear, this was on my old phone not my main phone, so I didn’t mind
testing it.

------
TheRealPomax
The article title is "Android: Why this photo is bricking some phones", which
more accurately reflects the experience for the overwhelming majority of
affected users. Would be good to update that.

------
jonnypotty
One of the biggest and most high profile software companies in the world can't
reliably read image files on their flagship phone.

People are scared of AGI. This sort of shit scares me more.

------
panpanna
TL;DR: color profile in the metadata could not be interpreted by some phones.
When you set that picture as your background it can cause your home screen to
hang.

Samsung fixed this with an extremely eraly June security update. I think it
took less than a week.

~~~
winter_blue
I wonder if Samsung will release this security update for phones released 3 or
4 years ago...

~~~
panpanna
This was not a real security issue, but in general they update even old
flagship devices for critical security issue.

IIRC, last time they had a really bad bug they updated some 4-5 year old
Notes.

------
neltnerb
I'm looking at this title and totally not willing to click on it... they don't
include the actual photo I would hope.

~~~
Al-Khwarizmi
They do, although they say the bug only happens if you set it as wallpaper.

I wouldn't click from a phone just in case, though.

~~~
bzb3
I clicked it from one of the affected phones and nothing happened. Saved it,
looked at it from the gallery... Nothing.

Seems like the crash is in some wallpaper-related code:
[https://news.ycombinator.com/item?id=23404772](https://news.ycombinator.com/item?id=23404772)

------
exabrial
FYI, it is not bricking phones, but that doesn't make a good headline.

It is making some of them unusable, requiring a hard reset.

~~~
gitgud
> It is making some of them unusable, requiring a hard reset.

Well that's still a " _soft brick_ " right?

------
dqpb
Fun fact, there are also images that can cause some human beings to crash.
Namely those that induce gamma oscillations such as black and white bar
patterns.

It would be interesting to train a generative NN on human EEG response to
create images that produce novel or unusual effects on the viewer.

~~~
wruza
There is McCollough effect, but it requires a long exposure to “crash” one’s
vision. Are there some examples of these patterns? (Beyond epilepsy-inducing
blinking, ofc)

~~~
dqpb
[https://pubmed.ncbi.nlm.nih.gov/28486114/](https://pubmed.ncbi.nlm.nih.gov/28486114/)

------
mbostleman
Is that Squaretop Mountain in the Wind River Range?

------
perlpimp
a photo I took on iphone x11 pro crashes my android when trying to set it as a
background, wonder if this is related.

------
chooseaname
Article says crash, not brick. Brick is not recoverable.

~~~
Hamuko
Soft bricks can be recovered from.

~~~
chooseaname
Neither the article nor the headline say soft brick. Besides, "soft brick" is
just someone not wanting to admit that brick has an understood definition but
they like the word brick and want to use it.

~~~
CathedralBorrow
Does brick have an understood definition though? I think this is the millionth
time I see this exact discussion about a news story using the term differently
from the one true definition. That doesn't seem very understood to me.

~~~
mhh__
It's so rare these days I really don't understand why people fuss over the
definition.

It's almost impossible to brick anything with software, and even in hardware
unless you damage the PCB itself you can usually recover if you tried hard
enough (e.g. Even if you fry a $1500 FPGA you could technically reflow a new
one and pray the bitstream is OK if you need it fixed _now_ \- although I'd
rather you than me)

~~~
OJFord
Technically you could also lay out new components and copper trace on an
actual brick, too.

I've always understood it to mean 'broken beyond software or high-level
firmware repair'. i.e. if not actually a blown component, something needs to
be reflashed which has an inaccessible JTAG header or something, rather than
something 'higher level' like recovery images over ADB & USB.

------
mister_hn
Bricking? I would say that a wipe can fix it.

------
parliament32
Crashing, not bricking. Can we update the title to remove the
editorialization?

~~~
Grazester
I have no idea why you are being down voted

~~~
ezequiel-garzon
My guess: because there is no editorialization here, since the BBC title also
says “bricking”. The title _must be editorialized_ if you want to change it.
Again, my guess. I used my upvote!

