Note: This is work-in-progress, last updated 2020-09-18 22:27:00 +0300, and I’ll continue in future when I have time…

Got my Pinephone yesterday (17th Sep 2020). This one is from the postmarketOS batch. Some first experiences here, and some initial research as I’m mostly interested seeing if this device can be hardened so much that I trust my private information and online accounts to be stored in it. I have no intentions of using PostmarketOS, I want plain Debian, even if it means rebuilding all packages.

First boot

So, on the first boot I was asked couple questions:

  • should postmarketOS be installed
  • what is my new PIN (for login)
  • if encryption should be enabled, and if yes, what should be the passphrase
  • if SSH server should be enabled

It took maybe 5-10 minutes to get everything ready. Then, I did some testing, but only couple minutes. My experience from that:

  • Firefox is horribly slow
  • no apps available to install, except calculator etc. that were already preinstalled
  • phone doesn’t ask for SIM card PIN - I had to explicitly choose to unlock SIM from menu
  • phone call kind of worked

First boot with UART -> USB

I happened to have UART to USB adapter already, so I just needed to toggle the DIP switch #6 to off from the phone, and then connect the cable.

I used screen for accessing the serial console. From trial and error (first try without baudrate defined) I soon discovered that required speed seems to be 115200.

screen /dev/ttyUSB0 115200
U-Boot SPL 2020.07-rc4 (Jul 18 2020 - 20:12:09 +0000)
DRAM: 2048 MiB
Trying to boot from MMC2
NOTICE:  BL31: v2.3():v20200428-1144-gc9348fdd36
NOTICE:  BL31: Built : 07:17:55, May 17 2020
NOTICE:  BL31: Detected Allwinner A64/H64/R18 SoC (1689)
NOTICE:  BL31: Found U-Boot DTB at 0x40649b0, model: Pine64 PinePhone (1.2)
NOTICE:  PSCI: System suspend is available via SCPI


U-Boot 2020.07-rc4 (Jul 18 2020 - 20:12:09 +0000) Allwinner Technology

CPU:   Allwinner A64 (SUN50I)
Model: Pine64 PinePhone (1.2)
DRAM:  2 GiB
MMC:   Device 'mmc@1c11000': seq 1 is in use by 'mmc@1c10000'
mmc@1c0f000: 0, mmc@1c10000: 2, mmc@1c11000: 1
Loading Environment from FAT... Unable to use mmc 1:1... In:    serial@1c28000
Out:   serial@1c28000
Err:   serial@1c28000
starting USB...
No working controllers found
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc1(part 0) is current device
Scanning mmc 1:1...
Found U-Boot script /boot.scr
959 bytes read in 1 ms (936.5 KiB/s)
## Executing script at 4fc00000
gpio: pin 98 (gpio 98) value is 1
gpio: pin 114 (gpio 114) value is 1
Booting from eMMC
arch=arm
baudrate=115200
board=sunxi
board_name=sunxi
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}${boot_syslinux_conf}
boot_net_usb_start=usb start
boot_prefixes=/ /boot/
boot_script_dhcp=boot.scr.uimg
boot_scripts=boot.scr.uimg boot.scr
boot_syslinux_conf=extlinux/extlinux.conf
boot_targets=fel mmc_auto usb0
bootargs=init=/init.sh rw console=tty0 console=ttyS0,115200 no_console_suspend earlycon=uart,mmio32,0x01c28000 panic=10 consoleblank=0 loglevel=1 cma=256M PMOS_NO_OUTPUT_REDIRECT PMOS_FORCE_PARTITION_RESIZE pmos_boot=/dev/mmcblk2p1 pmos_root=/dev/mmcblk2p2
bootcmd=run distro_bootcmd
bootcmd_fel=if test -n ${fel_booted} && test -n ${fel_scriptaddr}; then echo '(FEL boot)'; source ${fel_scriptaddr}; fi
bootcmd_mmc0=devnum=0; run mmc_boot
bootcmd_mmc1=devnum=1; run mmc_boot
bootcmd_mmc_auto=if test ${mmc_bootdev} -eq 1; then run bootcmd_mmc1; run bootcmd_mmc0; elif test ${mmc_bootdev} -eq 0; then run bootcmd_mmc0; run bootcmd_mmc1; fi
bootcmd_usb0=devnum=0; run usb_boot
bootdelay=2
bootdev=2
bootfstype=ext4
bootm_size=0xa000000
console=ttyS0,115200
cpu=armv8
devplist=1
dfu_alt_info_ram=kernel ram 0x40080000 0x1000000;fdt ram 0x4FA00000 0x100000;ramdisk ram 0x4FE00000 0x4000000
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
ethaddr=02:ba:d5:XX:XX:XX
fdt_addr_r=0x4FA00000
fdtcontroladdr=bbf49c20
fdtfile=allwinner/sun50i-a64-pinephone-1.2.dtb
fileaddr=4fc00000
filesize=3bf
kernel_addr_r=0x40080000
mmc_boot=if mmc dev ${devnum}; then devtype=mmc; run scan_dev_for_boot_part; fi
mmc_bootdev=1
partitions=name=loader1,start=8k,size=32k,uuid=${uuid_gpt_loader1};name=loader2,size=984k,uuid=${uuid_gpt_loader2};name=esp,size=128M,bootable,uuid=${uuid_gpt_esp};name=system,size=-,uuid=${uuid_gpt_system};
preboot=usb start
pxefile_addr_r=0x4FD00000
ramdisk_addr_r=0x4FE00000
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then run scan_dev_for_boot; fi; done; setenv devplist
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo SCRIPT FAILED: continuing...; fi
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scriptaddr=0x4FC00000
serial#=92c0XXXXXXXXXXXX
soc=sunxi
stderr=serial@1c28000
stdin=serial@1c28000
stdout=serial@1c28000
usb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boot_part; fi
uuid_gpt_esp=c12a7328-f81f-11d2-ba4b-00a0c93ec93b
uuid_gpt_system=b921b045-1df0-41c3-af44-4c6f280d3fae

Environment size: 3190/131068 bytes
Loading DTB
36309 bytes read in 3 ms (11.5 MiB/s)
Loading Initramfs
1435607 bytes read in 64 ms (21.4 MiB/s)
Loading Kernel
17823752 bytes read in 793 ms (21.4 MiB/s)
gpio: pin 115 (gpio 115) value is 1
Resizing FDT
Booting kernel
gpio: pin 116 (gpio 116) value is 1
gpio: pin 98 (gpio 98) value is 0
## Loading init Ramdisk from Legacy Image at 4fe00000 ...
   Image Name:   uInitrd
   Image Type:   AArch64 Linux RAMDisk Image (uncompressed)
   Data Size:    1435543 Bytes = 1.4 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 4fa00000
   Booting using the fdt blob at 0x4fa00000
   Loading Ramdisk to 49ea1000, end 49fff797 ... OK
   Loading Device Tree to 0000000049e95000, end 0000000049ea0fff ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.8.0 (pmos@build) (aarch64-alpine-linux-musl-gcc (Alpine 9.3.0) 9.3.0, GNU ld (GNU Binutils) 2.34) #4-postmarketos-allwinner SMP Wed Sep 16 08:16:30 UTC 2020
[    0.000000] Machine model: Pine64 PinePhone (1.2)
[    0.000000] earlycon: uart0 at MMIO32 0x0000000001c28000 (options '')
[    0.000000] printk: bootconsole [uart0] enabled
### postmarketOS initramfs ###
Configuring kernel firmware image search path
modprobe: module sun6i_mipi_dsi not found in modules.dep
modprobe: module sun4i_drm not found in modules.dep
modprobe: module pwm_sun4i not found in modules.dep
modprobe: module sun8i_mixer not found in modules.dep
modprobe: module ext4 not found in modules.dep
modprobe: module usb_f_rndis not found in modules.dep
NOTE: Waiting 10 seconds for the framebuffer /dev/fb0.
If your device does not have a framebuffer, disable this with:
no_framebuffer=true in <https://postmarketos.org/deviceinfo>
Setting framebuffer mode to: U:720x1440p-0
Setup usb network
  /sys/class/android_usb does not exist, skipping android_usb
  Setting up an USB gadget through configfs
Starting udhcpd
  Using interface usb0
  Start the dhcpcd daemon (forks into background)
Mount boot partition (/dev/mmcblk2p1) to /boot (read-only)
Extract /boot/initramfs-postmarketos-allwinner-extra
32199 blocks


Check/repair root filesystem (/dev/mapper/root)
e2fsck 1.45.6 (20-Mar-2020)
pmOS_root: clean, 24035/907120 files, 368172/3753472 blocks
Resize root filesystem (/dev/mapper/root)
resize2fs 1.45.6 (20-Mar-2020)
The filesystem is already 3753472 (4k) blocks long.  Nothing to do!

Mount root partition (/dev/mapper/root) to /sysroot (read-only)
Mount boot partition (/dev/mmcblk2p1) to /sysroot/boot (read-write)
umount: can't unmount /dev: Invalid argument

   OpenRC 0.42.1.9028084776 is starting up Linux 5.8.0 (aarch64)

/lib/rc/sh/init.sh: line 15: can't create /dev/null: Read-only file system
 * md5sum is missing, which suggests /usr is not mounted
 * If you have separate /usr, it must be mounted by initramfs
 * If not, you should check coreutils is installed correctly
 * Mounting /proc ... [ ok ]
 * Mounting /run ... * /run/openrc: creating directory
 * /run/lock: creating directory
 * /run/lock: correcting owner
/lib/rc/sh/init.sh: line 101: can't create /dev/null: Read-only file system
/lib/rc/sh/gendepends.sh: line 28: can't create /dev/null: Read-only file system
 * Caching service dependencies ... [ ok ]
 * Mounting devtmpfs on /dev ... [ ok ]
 * Mounting /dev/mqueue ... [ ok ]
 * Mounting /dev/pts ... [ ok ]
 * Mounting /dev/shm ... [ ok ]
 * Mount subpartitions of /dev/mmcblk2
device-mapper: reload ioctl on mmcblk2p1  failed: Resource busy
create/reload failed on mmcblk2p1
device-mapper: reload ioctl on mmcblk2p2  failed: Resource busy
create/reload failed on mmcblk2p2
 * Mounting /sys ... [ ok ]
 * Mounting security filesystem ... [ ok ]
 * Mounting debug filesystem ... [ ok ]
 * Mounting config filesystem ... [ ok ]
 * Mounting fuse control filesystem ... [ ok ]
 * Starting udev ... [ ok ]
 * Generating a rule to create a /dev/root symlink ... [ ok ]
 * Populating /dev with existing devices through uevents ... [ ok ]
 * Loading modules ... [ ok ]
 * Setting system clock using the hardware clock [UTC] ... [ ok ]
 * Checking local filesystems  ... [ ok ]
 * Remounting root filesystem read/write ... [ ok ]
 * Remounting filesystems ... [ ok ]
 * Mounting local filesystems ... [ ok ]
 * Configuring kernel parameters ...sysctl: error: 'net.ipv4.tcp_syncookies' is an unknown key
sysctl: error: 'kernel.unprivileged_bpf_disabled' is an unknown key
sysctl: error: 'kernel.sysrq' is an unknown key
 [ ok ]
 * Creating user login records ... [ ok ]
 * Wiping /tmp directory ... [ ok ]
 * Setting hostname ... [ ok ]
 * Starting busybox syslog ... [ ok ]
 * Starting System Message Bus ... [ ok ]
 * Starting Bluetooth ... [ ok ]
 * Starting RNG Daemon ... [ ok ]
 * Starting WPA Supplicant ... [ ok ]
 * Starting networkmanager ... [ ok ]
 * Starting chronyd ... [ ok ]
 * Enabling EG25 WWAN module ... * Starting gpsd ... [ ok ]
 * Starting iio-sensor-proxy ... [ ok ]
 * /run/lightdm: creating directory
 * /run/lightdm: correcting owner
 * Starting Display Manager ... [ ok ]
 * Starting modemmanager ... [ ok ]
 * Activating swap file ...Configured swap file size is 0, skipping creation.
 [ ok ]
 * Starting local ... [ ok ]

Welcome to postmarketOS
Kernel 5.8.0 on an aarch64 (/dev/ttyS0)
pine64-pinephone login: 


First thoughts from the log

  • quite many errors
  • OpenRC should be replaced with systemd for my own use…
  • I’d really like to enter decryption password via UART
  • can we harden U-Boot? Maybe support for high assurance boot or similar to restrict software this devices is able to run?

Login via UART connection

Username is user, and password is the screen lock password you chose earlier. So, via UART connection you can probably bruteforce your number-only PIN, unless there is some PAM lockdown configured…

pine64-pinephone login: user
Password: 
Welcome to postmarketOS!

This distribution is based on Alpine Linux.
Read both our wikis to find a large amount of how-to guides and
general information about administrating and development.
See <https://wiki.postmarketos.org> and <https://wiki.alpinelinux.org>.

You may change this message by editing /etc/motd.

pine64-pinephone:~$ uname -a
Linux pine64-pinephone 5.8.0 #4-postmarketos-allwinner SMP Wed Sep 16 08:16:30 UTC 2020 aarch64 Linux
pine64-pinephone:~$ id
uid=10000(user) gid=10000(user) groups=10(wheel),18(audio),23(input),27(video),28(netdev),101(plugdev),10000(user)
pine64-pinephone:~$ 

and you can escalate to root using sudo:

pine64-pinephone:~$ sudo -i

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for user: 
pine64-pinephone:~# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

Looking around

Users

There seemed to be lots of system users, but all those had no password (! in their /etc/shadow entries).

Contents of sudoers was just

pine64-pinephone:/etc# cat sudoers |grep -v ^# |grep -v ^$
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL

What services listening?

I was first interested about the services running on the host, and there was no ss command available, which is my go-to tool for these things… So, let’s install it. As we’re running on Alpine-based OS, apk is the tool for installing new packages:

apk add iproute2

and this was the results…

pine64-pinephone:/etc# ss -nlpxtu
Netid State  Recv-Q Send-Q                        Local Address:Port Peer Address:PortProcess
u_str LISTEN 0      0           /var/run/dbus/system_bus_socket 3966            * 0    users:(("dbus-daemon",pid=2286,fd=4))
u_str LISTEN 0      0                     @/sys/entropy/haveged 3990            * 0    users:(("haveged",pid=2336,fd=3))
u_str LISTEN 0      0                        /var/run/gpsd.sock 6664            * 0    users:(("gpsd",pid=2486,fd=3))
u_str LISTEN 0      0           /run/user/10000/keyring/control 6777            * 0    users:(("gnome-keyring-d",pid=2714,fd=6))
u_str LISTEN 0      0                        @/tmp/.X11-unix/X0 6806            * 0    users:(("Xwayland",pid=2849,fd=18),("phoc",pid=2719,fd=18))
u_str LISTEN 0      0                         /tmp/.X11-unix/X0 6807            * 0    users:(("Xwayland",pid=2849,fd=19),("phoc",pid=2719,fd=19))
u_str LISTEN 0      0                     @/tmp/dbus-mdvTU2VyQC 6873            * 0    users:(("dbus-daemon",pid=2800,fd=5))
u_str LISTEN 0      0         /run/user/10000/pulse/dbus-socket 6890            * 0    users:(("pulseaudio",pid=2830,fd=28))
u_str LISTEN 0      0              /run/user/10000/pulse/native 6894            * 0    users:(("pulseaudio",pid=2830,fd=29))
u_str LISTEN 0      0                 /run/user/10000/wayland-0 7655            * 0    users:(("phoc",pid=2719,fd=24),("phoc",pid=2719,fd=23))
u_str LISTEN 0      0               /run/user/10000/keyring/ssh 7680            * 0    users:(("gnome-keyring-d",pid=2714,fd=12))
u_str LISTEN 0      0                     @/tmp/dbus-7O4Q4E32QL 8445            * 0    users:(("dbus-daemon",pid=2718,fd=5))
u_str LISTEN 0      0      /var/run/NetworkManager/private-dhcp 8452            * 0    users:(("NetworkManager",pid=2397,fd=17))
u_str LISTEN 0      0                      @/tmp/.ICE-unix/2759 8533            * 0    users:(("gnome-session-b",pid=2759,fd=10))
u_str LISTEN 0      0                       /tmp/.ICE-unix/2759 8534            * 0    users:(("gnome-session-b",pid=2759,fd=11))
u_str LISTEN 0      0            /run/user/10000/keyring/pkcs11 9279            * 0    users:(("gnome-keyring-d",pid=2714,fd=13))
u_str LISTEN 0      0                                @qmi-proxy 9752            * 0    users:(("qmi-proxy",pid=3120,fd=5))
u_seq LISTEN 0      0                         /run/udev/control 402             * 0    users:(("udevd",pid=1873,fd=4))
udp   UNCONN 0      0                                   0.0.0.0:67        0.0.0.0:*    users:(("udhcpd",pid=1230,fd=5))
udp   UNCONN 0      0                                10.0.2.158:68        0.0.0.0:*    users:(("dhcpcd",pid=2745,fd=9))
tcp   LISTEN 0      5                                 127.0.0.1:2947      0.0.0.0:*    users:(("gpsd",pid=2486,fd=4))
tcp   LISTEN 0      5                                     [::1]:2947         [::]:*    users:(("gpsd",pid=2486,fd=5))

From very same package we also get ip command, so let’s see the interfaces

pine64-pinephone:/etc# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:XX:XX:XX brd 00:00:00:XX:XX:XX
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: usb0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether 0a:2f:1a:XX:XX:XX brd ff:ff:ff:XX:XX:XX
    inet 172.16.42.1/16 brd 172.16.255.255 scope global usb0
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 02:ba:d5:XX:XX:XX brd ff:ff:ff:XX:XX:XX
    inet 10.0.2.158/24 brd 10.0.2.255 scope global dynamic wlan0
       valid_lft 84233sec preferred_lft 84233sec
    inet6 fe80::XXXX:XXXX:XXX:XXXX/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
4: wwan0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/none 
    inet6 fe80::XXX:XXXX:XXX:XXXX/64 scope link stable-privacy 
       valid_lft forever preferred_lft forever

Misc

Battery state

pine64-pinephone:~$ upower -i $(upower -e |grep -i battery)
  native-path:          axp20x-battery
  power supply:         yes
  updated:              Tue Sep 22 09:44:29 2020 (75 seconds ago)
  has history:          yes
  has statistics:       yes
  battery
    present:             yes
    rechargeable:        yes
    state:               charging
    warning-level:       none
    energy:              0 Wh
    energy-empty:        0 Wh
    energy-full:         0 Wh
    energy-full-design:  0 Wh
    energy-rate:         0 W
    voltage:             3.504 V
    percentage:          4%
    capacity:            100%
    icon-name:          'battery-caution-charging-symbolic'
  History (charge):
    1600760669  4.000   charging

Feedback / comments?

Ping me (@ypcs) on Twitter