Commit graph

94 commits

Author SHA1 Message Date
Thiébaud Weksteen
cc2fb50f52 Add documentation on mkdir about seclabel
Test: n/a
Change-Id: Iab672b4755a259caacf495a6692afcb268b4205f
2022-05-31 14:47:13 +10:00
Jaegeuk Kim
120f6b260c Init: add dev.mnt.blk.bootdevice to access device sysfs
This patch adds a new property, 'dev.mnt.root.<mount_point>', which provides,
for example of /data,

1. dm-N
  dev.mnt.dev.data = dm-N
  dev.mnt.blk.data = sdaN or mmcblk0pN
  dev.mnt.rootdisk.data = sda or mmcblk0

2. sdaN or mmcblk0pN
  dev.mnt.dev.data = sdaN or mmcblk0pN
  dev.mnt.blk.data = sdaN or mmcblk0pN
  dev.mnt.rootdisk.data = sda or mmcblk0

Signed-off-by: Jaegeuk Kim <jaegeuk@google.com>
Change-Id: I0a58a62d416f966f26b5de04112c2f9a7eceb22c
2022-03-14 16:59:52 -07:00
Devin Moore
07ec259a54 Update init/README.md to mention bootconfig for androidboot argument
In Android S and later, androidboot.* kernel cmdline parameters are
moved to bootconfig instead the kernel cmdline. This includes the
androidboot.force_normal_boot.

Bug: 219951268
Test: N/A
Change-Id: Id0328ad09a34d654de9936e37a576a8a9f44de6c
2022-02-25 17:04:45 +00:00
David Anderson
6d7c7a2156 init: Add --only-if-running argument to restart command.
If surfaceflinger crashes before zygote starts, it will restart zygote
too early. Add this argument will allow it to only restart zygote if
it's already running.

Bug: 197224273
Test: manual test
Change-Id: I0ac8dbeaf0a002f8cfcfcc0f63d4b90d08393c5c
2021-12-03 15:49:39 -08:00
David Anderson
2285b528de init: Add a way to class_restart only enabled services.
class_restart accidentally restarts disabled services. Changing this
behavior is risky as it could break compatibility. Instead, add an
"--only-enabled" argument to class_restart to opt-in to the new
functionality. This syntax is backward compatible, as previously only a
1-argument form was accepted.

Bug: 190065372
Bug: 198105685
Test: add a class_restart action and a disabled service, make sure
      service is not restarted.
Change-Id: Idb08779de7ac7a21e23f8b8a3276bd5a66a43299
2021-11-12 22:31:12 +00:00
Eric Biggers
dd41635cef init: remove the class_{start,reset}_post_data commands
Remove the class_start_post_data and class_reset_post_data commands,
since they aren't used anymore.  They were only used on devices that
used FDE (Full Disk Encryption), via actions in rootdir/init.rc.  These
actions have been removed, since support for FDE has been removed.
There is no use case for these commands in vendor init scripts either.

Keep the mark_post_data command, since DoUserspaceReboot() uses the
post-data service flag even on non-FDE devices.

Bug: 191796797
Change-Id: Ibcd97543daa724feb610546b5fc2a0dd7f1e62e7
2021-11-11 14:36:47 -08:00
Bowgo Tsai
5998c74d7a Sets 'verity_update_state' in init.rc
This is required since Android 12, because
CtsNativeVerifiedBootTestCases will read property
"partition.${partition}.verified.hash_alg" to
check that sha1 is not used.

Also see https://r.android.com/1546980 for more details.

Bug: 175236047
Bug: 203720638
Test: build and boot a device
Change-Id: I300265f4af9c2781d40537f391bda9eaf62c27ba
2021-10-21 21:38:22 +08:00
Ray Essick
35ffd69db5 Versioning for apex init.rc files
Support an "init.#rc" versioning scheme for apex init files.
chooses highest # <= current system sdk.
".rc" (aka the old init.rc) is treated as sdk 0
Document these semantics in README.md

Bug: 198186200
Test: booting, lots of logcat output
Change-Id: I2d0405be73dae9bafa6f22535b29ed6b053ddbc4
2021-10-11 19:02:47 -07:00
Jooyung Han
f0e03fdac3 doc: verity_update_state has no args
`verity_update_state` command doesn't have a <mount-point> arg.

Bug: n/a
Test: n/a (documentation updated)
Change-Id: I6a807f8cce05c8669e85fe5cea935fbd668aa678
2021-09-09 15:46:41 +09:00
Eric Biggers
d14a178d01 Revert "init: make reboot_on_failure not apply to manually stopped services"
This reverts commit 1c51525f66 because it
accidentally made reboot_on_failure be a no-op for all services.  This
is because Reap() itself calls KillProcessGroup() on devices with a
vendor level >= R, which in turn sets SVC_STOPPING.  I had overlooked
this somehow, probably because I didn't consider that a service can
consist of multiple processes.

It turns out that real FDE devices don't actually need the above commit
because FDE devices aren't allowed to have updatable apexes enabled, and
without updatable apexes enabled, apexd exits automatically and
therefore doesn't have to be stopped.  This can be verified by using the
aosp_cf_x86_phone_noapex build target, rather than aosp_cf_x86_phone
which I had used for testing before.  So just revert it for now.

Bug: 194370048
Change-Id: I90eddf2a87397449b241e5acaaa8d4a4241d73a9
2021-07-22 13:06:41 -07:00
David Anderson
8ce8c89b35 Add some README.md text for init triggers.
Bug: 180475195
Test: N/A
Change-Id: I33ec5a03b6aced835f15315b1755e17d07969d4c
2021-06-01 21:38:41 -07:00
Eric Biggers
1c51525f66 init: make reboot_on_failure not apply to manually stopped services
Add a new service flag SVC_STOPPING which tracks whether a service is
being manually stopped by init, and make the "reboot_on_failure" service
setting not apply when SVC_STOPPING is set.

This is needed for devices that use FDE, because otherwise the device
reboots during the following init script fragment:

    on property:vold.decrypt=trigger_shutdown_framework
        class_reset late_start
        class_reset main
        class_reset_post_data core
        class_reset_post_data hal

... because that stops all services, including apexd which has been
marked with reboot_on_failure since
https://android-review.googlesource.com/c/platform/system/apex/+/1325212.
So init was killing apexd, then rebooting the device because apexd
"failed" due to having been killed.  Making reboot_on_failure not apply
when init stops a service itself fixes the problem.

This is one of a set of changes that is needed to get FDE working again
so that devices that launched with FDE can be upgraded to Android 12.

Bug: 186165644
Test: Tested FDE on Cuttlefish
Change-Id: I599f7ba107e6c126e8f31d0ae659f0ae672a25e4
2021-05-03 21:38:50 -07:00
satayev
7f9fabad4f Merge "Introduce load_exports action." 2021-02-22 17:14:19 +00:00
Artur Satayev
500946b637 Introduce load_exports action.
The action reads a file with individual `export` actions declared on
each line, and calls `setenv` for each.

See go/updatable-classpath for details on how this is going to be used.

Bug: 180105615
Test: manual
Change-Id: I5390e52cf8ffd9c3babf31ed854eeecc727351eb
2021-02-19 17:12:26 +00:00
Lisa Liu
08c862fa00 init: ro.boottime.init.modules
Add a property ro.boottime.init.modules to provide kernel modules
loading time in milliseconds. Also add corresponding log to show in init
log along with loaded module count.

Test: boot test
Bug: 178143513
Change-Id: I77e3939c2a271da6841350a8c2a34ad32f637377
2021-02-19 15:59:04 +08:00
Woody Lin
ef9d460ea8 Add init.svc_debug.no_fatal.<svc_name> to skip SVC_CRITICAL
For user who would like to retain the crash symptom and avoid device
from power cycle for live debugging, set
init.svc_debug.no_fatal.<svc_name> to "true" to skip FATAL reboot.

Bug: 177593855
Change-Id: I0bdb6191e5963c08e1ea301a60060acf916dd49b
2021-01-22 15:01:36 +08:00
Wei Wang
49d2598166 init: add a copy_per_line built-in command
There are sysfs nodes that don't take multiple inputs, adding a new
copy_per_line built-in command to copy from source file to destination
line by line.

Bug: 171740453
Test: boot and check file and log
Change-Id: I41b7a565829299d56b81d4509525dfa6a0a52444
2020-11-20 10:54:14 -08:00
Woody Lin
45215ae6e5 init/service_parser: Add arguments window' and target' for `critical'
The critical services can now using the interface `critical
[window=<fatal crash window mins>] [target=<fatal reboot target>]` to
setup the timing window that when there are more than 4 crashes in it,
the init will regard it as a fatal system error and reboot the system.

Config `window=${zygote.critical_window.minute:-off}' and
`target=zygote-fatal' for all system-server services, so platform that
configures ro.boot.zygote_critical_window can escape the system-server
crash-loop via init fatal handler.

Bug: 146818493
Change-Id: Ib2dc253616be6935ab9ab52184a1b6394665e813
2020-10-26 11:38:01 +08:00
Tom Cherry
34ee04762a init: guarantee the ordering that actions are executed in
The README.md states that this ordering is not guaranteed to give
flexibility for the future, however it's time to state that this
ordering is guaranteed, especially since:

1) We have a tests, EventTriggerOrder and
   EventTriggerOrderMultipleFiles, which have guaranteed this ordering
   since 2017.
2) We have users requesting and depending on this order

Also update some slightly out of date parts of the documentation:
1) We import /system/etc/init/hw/init.rc instead of /init.rc as the
   first import
2) We additionally import /system_ext/etc/init and /product/etc/init

Test: n/a
Change-Id: I6d7b8d9e52f0d52bee320d5074ebb74a537f9150
2020-10-01 11:07:43 -07:00
Steven Moreland
fa2457e1cd init README: document AIDL service interface
There is documentation for how AIDL works with ctl commands or
interface_start commands, however it seems we were missing documentation
on declaration of interfaces.

Bug: N/A
Test: N/A
Change-Id: I0e5d2350b6b847a870eafbc69828e75f1f6ca4f0
2020-07-10 17:53:18 +00:00
Amos Bianchi
16bfe099f3 Fix typo in android init language documentation.
Test: N/A
Change-Id: I158294b59f120f5f1296f3c9e6e5357fb02ed6b8
2020-06-09 17:10:49 -07:00
Treehugger Robot
389d8885a8 Merge "init: fix README.md about perform_apex_configs" 2020-06-09 15:06:54 +00:00
Alistair Delva
de28a8651f Respect ro.boot.fstab_suffix in swapon_all
While mount_all and umount_all were updated to use ro.boot.fstab_suffix,
I neglected to update swapon_all. Trivially copied from umount_all.

Bug: 142424832
Change-Id: Icd706fe7a1fe16c687cd2811b0a3158d7d2e224e
Merged-In: Icd706fe7a1fe16c687cd2811b0a3158d7d2e224e
2020-06-08 23:41:40 +00:00
Alistair Delva
6c6a36fb31 Add documentation for umount_all
The mount_all and swapon_all commands are documented, but umount_all
is not. Add some documentation.

Bug: 142424832
Change-Id: I7e4dcb4d222b787350a79c9e312062cac9eeb4d8
2020-06-08 10:51:40 -07:00
Jooyung Han
ea138c8695 init: fix README.md about perform_apex_configs
parse_apex_configs was renamed with
13e51e7f0b.

Bug: n/a
Test: n/a
Change-Id: I6e60d64f915fa9ed47c5ec1195a9b371f68f1134
2020-06-08 18:22:15 +09:00
Alistair Delva
a2cc1ebb72 Add ro.boot.fstab_suffix and modify mount_all to use it
Currently the ReadDefaultFstab function, which calls GetFstabPath,
makes some assumptions about what the fstab will be called and where
it is located. This is being used by vold to set up userdata encryption
and for gsid, and is even used in the default boot control HAL, so it
has become quite baked.

The original way for a board to specify things to mount was to use the
"mount_all /path/to/fstab" command in init.rc. However, due to the
above functionality, the path after mount_all is no longer very useful,
as it cannot differ from the inferred path, or userdata encryption and
other features will be broken.

On Cuttlefish, we have an interest in being able to test alternative
userdata configurations (ext4 vs f2fs, encryption on/off, etc.) and
currently the only way to achieve this is to either a) modify the
ro.hardware or ro.hardware.platform properties, which breaks a bunch
of things like default HAL filenames, or regenerate our odm.img or
vendor.img filesystems. We can't simply install another fstab and
point to it with "mount_all".

This change allows the fstab path to be omitted from "mount_all", and
adds another property which overrides the existing checks for
fstab.${ro.hardware} and fstab.${ro.hardware.platform}. Specifying
${ro.boot.fstab_suffix} will cause fstab.${ro.boot.fstab_suffix}
to be checked first.

Bug: 142424832
Test: booted cuttlefish with 'mount_all ${ro.hardware} --late'
Test: booted cuttlefish with 'mount_all --late'
Test: booted cuttlefish with 'mount_all --late' and fstab_suffix=f2fs
Test: partially booted cuttlefish with 'mount_all ${ro.hardware}'
Test: partially booted cuttlefish with 'mount_all'
Change-Id: I3e10f66aecfcd48bdb9ebf1d304b7aae745cbd3c
2020-05-21 16:38:40 -07:00
Mark Salyzyn
ffa52e9c6f init: support wait timeout with more precision
A one second timeout is so coarse and can affect boot time when
the possibility that the file does not exist.  Switch to accepting
a floating point number for seconds for the wait for file command.

Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Bug: 151950334
Test: wait_for_file sleep 0.05 reports an appropriate delay
Change-Id: I8d8ed386519ab54270b05ce91663d0add30f12e7
2020-05-15 01:18:24 +00:00
Suren Baghdasaryan
c9c0bbac53 init: Add task_profiles init command
Introduce new command to allow setting task profiles from inside .rc
script. This is to replace usage of writepid when a service is trying
to join a cgroup. Usage example from a .rc file:

service surfaceflinger /system/bin/surfaceflinger
    task_profiles HighPerformance

Bug: 155419956
Test: change .rc file and confirm task profile is applied
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Change-Id: I0add9c3b363a7cb1ea89778780896cae1c8a303c
2020-04-30 22:24:21 +00:00
Tom Cherry
bdbf5047c9 init: add ctl.oneshot_on/ctl.oneshot_off
Some services are lazy HALs on some platforms and not lazy HALs on
others; this is known at runtime by hwservicemanager, so this change
adds these properties to allow hwservicemanager to turn one oneshot
(for lazy HALs).  It may also be required to make a lazy HAL not lazy
anymore, and oneshot_off is provided for this.

Bug: 147841742
Test: new unit test that turn on and off oneshot on a service (bootanim)
      and observes that it follows the expected behavior
Change-Id: I79524e2c9a5008f90c8d3bc40920fde00602a439
2020-03-19 12:54:25 -07:00
Tom Cherry
504eb85f9d init: document interface_* commands and ctl.* actions
Test: n/a
Change-Id: Ided7e16a00142e7235edeef3be2eddb6bb751bfc
2020-01-13 09:45:08 -08:00
Anton Hansson
8c4d930805 Point to exec_start from start in init documentation
Since it mentions a caveat, it's nice to know how to avoid
that caveat.

Test: N/A
Change-Id: I487f1080058bf83a76a725735c6f283f88b0739e
2019-12-05 15:37:09 +00:00
Paul Crowley
68258e8444 Make encryption action an argument to mkdir
FscryptSetDirectoryPolicy no longer tries to infer the action from the
filename. Well mostly; it still assumes top-level directories in /data
should be encrypted unless the mkdir arguments say otherwise, but
it warns.

Bug: 26641735
Test: boot, check log messages
Change-Id: Id6d2cea7fb856f17323897d85cf6190c981b443c
2019-11-05 16:26:43 -08:00
Tom Cherry
9328021ce7 init: add tips for debugging linker errors when launching init services
Test: we can see linker errors in dmesg when following these tips
Change-Id: I86b65e01d06ed7c0b908c4512d55872cd5595eca
2019-09-26 15:24:40 -07:00
Tom Cherry
f74b7f5756 init: add stdio_to_kmsg option
Some services are not native android services and therefore don't log
via the normal mechanisms.  This gives developers an option to have
their stdout/stderr logs sent directly to kmsg.

Test: see test prints to kernel log
Change-Id: I7973ea74d5cab3a90c2cd9a3d5de2266439d0c01
2019-09-24 12:47:14 -07:00
Tom Cherry
60971e6ce2 init: add reboot_on_failure service option
This replaces the recently added `exec_reboot_on_failure` builtin, since
it'll be cleaner to extend service definitions than extending `exec`.
This is in line with what we decided when adding `exec_start` instead
of extending `exec` to add parameters for priority.

Test: `exec_start` a service with a reboot_on_failure option and watch
      the system reboot appropriately when the service is not found and when
      the service terminates with a non-zero exit code.

Change-Id: I332bf9839fa94840d159a810c4a6ba2522189d0b
2019-09-13 16:48:35 +01:00
Tom Cherry
2e4c85f157 init: clean up file / socket descriptor creation
clang-tidy hinted that some of this code wasn't right.  Looking
deeper, there is really not much related to file and socket
descriptors, except that they're published in similar ways to the
environment.  All of the abstraction into a 'Descriptor' class takes
us further away from specifying what we really mean.

This removes that abstraction, adds stricter checks and better errors
for parsing init scripts, reports sockets and files that are unable to
be acquired before exec, and updates the README.md for the passcred
option.

Test: build, logd (uses files and sockets) works
Change-Id: I59e611e95c85bdbefa779ef69b32b9dd4ee203e2
2019-07-15 12:17:30 -07:00
Daniel Norman
d6d09c646a Qualifies the mention of lazily starting services from 'interface'.
The 'interface' option is not always used by services that support lazy
startup.

Test: None
Change-Id: I6bfb095d4ecb932933d56cd1859a5eff6df2edbd
2019-06-18 17:03:05 -07:00
Tom Cherry
3041a5100b init: don't import rc files during mount_all after Q
Importing rc files during mount_all was at best a stop gap until
Treble's first stage mount and at worst a bad idea.  It doesn't have a
reason to exist now that first stage mount exists and is required, and
always had edge cases where init could not handle loading some aspects
of scripts after it had started processing actions.

This change removes this functionality for devices launching after Q.

Test: devices boot
Change-Id: I3181289572968637b884e150d36651f453d40362
2019-05-21 17:48:33 -07:00
Martijn Coenen
acc45aa0a1 class_start_post_data also starts disabled services.
This keyword was introduced to support restarting services on devices
using APEX and FDE. The current implementation is not a restart, but
rather a 'reset' followed by a 'start', because the real /data must be
mounted in-between those two actions. But we effectively want this to be
a restart, which means that we also want to start 'disabled' services
that were running at the time we called 'class_reset_post_data'.

To implement this, keep track of whether a service was running when its
class was reset at post-data, and start all those services.

Bug: 132592548
Test: manual testing on FDE Taimen
Change-Id: I1e81e2c8e0ab2782150073d74e50e4cd734af7b9
Merged-In: I1e81e2c8e0ab2782150073d74e50e4cd734af7b9
2019-05-16 09:30:35 +02:00
Mark Salyzyn
10377df9f8 init: ro.boottime.init.first_stage
Add a property ro.boottime.init.first_stage to provide us a
first stage init duration from start to exec completed in
nanoseconds.

For consistency, report nanoseconds duration for
ro.boottime.init.selinux as well instead of milliseconds.
Now also report consistently from start to exec completed
instead of just the selinux load time.

SideEffects: ro.boottime.init.selinux is reported to TRON and
             may alarm with the millionfold increase in precision.
             ro.boottime.init is now also consistent with ns
             precision.

Test: inspect
Bug: 124491153
Bug: 129780532
Change-Id: Iff4f1a3a1ab7ff0a309c278724c92da0832b9a69
2019-05-08 16:07:10 +00:00
Martijn Coenen
fc78be2935 Merge "Support for stopping/starting post-data-mount class subsets." 2019-05-07 06:41:01 +00:00
Tom Cherry
1cd30df584 Merge "Vboot1.0: remove code to read verity state in userspace" 2019-05-06 23:41:47 +00:00
Zimuzo
88de80fc53 Attempt native rollback for frequent crashes before boot completed
Before, if updatable processes crash 4 times in 4mins, a native
rollback will be attempted. This behavior does not detect
system_server early boot deadlocks because the system server requires
at least a min to detect a deadlock, and crash itself. The crashes
don't happen frequently enough for init to detect.

After, this cl, the old behavior exists and additionally, init detects
*any* 4 crashes of updatable processes before boot completed,
regardless of if they happen within 4mins or not.

Test: Manually tested by adding artificial sleep in system_server so
deadlock is triggered before boot. system_server crashes 4 times in
over 4mins and the ro.init.updatable_crashing prop is set to 1.
Bug: 129597207

Change-Id: Ie6fb5693ff4be105bcbe139c22850fb076e40260
2019-04-30 11:19:19 +00:00
Martijn Coenen
70788f93ba Support for stopping/starting post-data-mount class subsets.
On devices that use FDE and APEX at the same time, we need to bring up a
minimal framework to be able to mount the /data partition. During this
period, a tmpfs /data filesystem is created, which doesn't contain any
of the updated APEXEs. As a consequence, all those processes will be
using the APEXes from the /system partition.

This is obviously not desired, as APEXes in /system may be old and/or
contain security issues. Additionally, it would create a difference
between FBE and FDE devices at runtime.

Ideally, we restart all processes that have started after we created the
tmpfs /data. We can't (re)start based on class names alone, because some
classes (eg 'hal') contain services that are required to start apexd
itself and that shouldn't be killed (eg the graphics HAL).

To address this, keep track of which processes are started after /data
is mounted, with a new 'mark_post_data' keyword. Additionally, create
'class_reset_post_data', which resets all services in the class that
were created after the initial /data mount, and 'class_start_post_data',
which starts all services in the class that were started after /data was
mounted.

On a device with FBE, these keywords wouldn't be used; on a device with
FDE, we'd use them to bring down the right processes after the user has
entered the correct secret, and restart them.

Bug: 118485723
Test: manually verified process list
Change-Id: I16adb776dacf1dd1feeaff9e60639b99899905eb
2019-04-26 14:04:59 +02:00
Tom Cherry
f7545cea34 Vboot1.0: remove code to read verity state in userspace
The code to read verity state in userspace is deprecated in favor of
having the bootloader read and report the state, so this change
removes this now unused code.

Bug: 73456517
Test: boot
Change-Id: Ib626fd61850bce3016179ca92a9831c2ac29c032
2019-04-19 16:53:33 -07:00
Elliott Hughes
8457f52ba9 init: fix loglevel docs.
Bug: http://b/129989984
Test: N/A
Change-Id: Ie7b320fd47dec839ad79d677eb90050cfbcf50c3
2019-04-15 12:17:22 -07:00
Mark Salyzyn
b833d17de2 init: fixes to README.mk
Corrected a few technical, spelling and grammar errors.

Test: none
Bug: 129780532
Change-Id: Ia05f44c782d94a3bb4224fc6929ac325852e0c41
2019-04-08 10:06:49 -07:00
Vic Yang
87215c2530 Fix parse_apex_configs doc in README.md
Test: None
Change-Id: I0871e640cfcab706a5396e3824a1f75239c29840
2019-03-21 11:59:29 -07:00
Mark Salyzyn
a73ed22cb7 init: add MountHandler property handler
Set properties dev.mnt.blk.<mount_point>=<device_block_class> for mount
and umount operations by setting up an Epoll handler to catch
EPOLLERR or EPOLLPRI signals when /proc/mounts is changed.  Only
update properties associated with block devices.  For the mount
point of /, use the designation of /root instead.

Can use the properties in init rc expansion like:

on property dev.mnt.blk.root=*
    write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${boot_read_ahead_kb:-2048}

on property dev.mnt.blk.data=*
    write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${boot_read_ahead_kb:-2048}

on late-fs
    setprop boot_read_ahead_kb 128
    write /sys/block/${dev.mnt.blk.root}/queue/read_ahead_kb ${boot_read_ahead_kb}
    write /sys/block/${dev.mnt.blk.data}/queue/read_ahead_kb ${boot_read_ahead_kb}

Test: boot and inspect getprop results.
Bug: 124072565
Change-Id: I1b8aff44f922ba372cd926de2919c215c40ee874
2019-03-15 11:54:38 -07:00
Tom Cherry
1cd082d421 init: allow services to have no capabilities set
In particular, this allows services running as the root user to have
capabilities removed instead of always having full capabilities.

Test: boot device with a root service with an empty capabilities
      option in init showing no capabilities in /proc/<pid>/status
Change-Id: I569a5573ed4bc5fab0eb37ce9224ab708e980451
2019-02-06 11:25:18 -08:00