Skip to content

Commit 5f0814b

Browse files
committed
stub: Re-copy AdminUserRecoveryInfo.plist on repair
This lets users fix Asahi installs after a macOS reinstall (which breaks the machine owner credentials previously used). Signed-off-by: Hector Martin <[email protected]>
1 parent 3fb1e17 commit 5f0814b

2 files changed

Lines changed: 56 additions & 24 deletions

File tree

src/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ def action_repair_or_upgrade(self, oses, upgrade):
411411
return False
412412

413413
self.dutil.remount_rw(self.ins.osi.system)
414+
self.ins.repair(self.cur_os)
414415

415416
if upgrade:
416417
# Note: we get the vars out of the boot.bin in the system volume instead of the

src/stub.py

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ def get_paths(self):
124124
self.sv_path = os.path.join(self.core_services, "SystemVersion.plist")
125125
self.sv_dis_path = os.path.join(self.core_services, "SystemVersion-disabled.plist")
126126
self.icon_path = os.path.join(self.osi.system, ".VolumeIcon.icns")
127+
self.pb_vgid = os.path.join(self.osi.preboot, self.osi.vgid)
127128

128129
def check_existing_install(self, osi):
129130
self.osi = osi
@@ -166,6 +167,48 @@ def path(self, path):
166167
def open(self, path):
167168
return self.pkg.open(self.path(path))
168169

170+
def copy_admin_users(self, cur_os):
171+
logging.info("Copying admin users")
172+
173+
os.makedirs(os.path.join(self.pb_vgid, "var/db"), exist_ok=True)
174+
admin_users = os.path.join(cur_os.preboot, cur_os.vgid, "var/db/AdminUserRecoveryInfo.plist")
175+
tg_admin_users = os.path.join(self.pb_vgid, "var/db/AdminUserRecoveryInfo.plist")
176+
if os.path.exists(tg_admin_users):
177+
self.chflags("noschg", tg_admin_users)
178+
shutil.copy(admin_users, tg_admin_users)
179+
180+
self.copy_idata.append((tg_admin_users, "AdminUserRecoveryInfo.plist"))
181+
182+
admin_users = plistlib.load(open(tg_admin_users, "rb"))
183+
self.stub_info["admin_users"] = {}
184+
for user, info in admin_users.items():
185+
self.stub_info["admin_users"][user] = {
186+
"uid": info["GeneratedUID"],
187+
"real_name": info["RealName"],
188+
}
189+
190+
# Stop macOS <12.0 bootability stufff from clobbering this file
191+
self.chflags("schg", tg_admin_users)
192+
193+
def repair(self, cur_os):
194+
self.get_paths()
195+
self.copy_admin_users(cur_os)
196+
197+
if self.osi.attached_partitions:
198+
logging.info("Found attached partitions")
199+
efi_part = self.osi.attached_partitions[0]
200+
if efi_part.type != "EFI":
201+
logging.info("EFI partition not found")
202+
else:
203+
logging.info("EFI partition found")
204+
mountpoint = self.dutil.mount(efi_part.name)
205+
asahi = os.path.join(mountpoint, "asahi")
206+
if os.path.exists(asahi):
207+
self.collect_installer_data(asahi, merge_stub_info=True)
208+
logging.info("Admin users updated in ESP")
209+
else:
210+
logging.info("'asahi' dir not found in ESP")
211+
169212
def install_files(self, cur_os):
170213
logging.info("StubInstaller.install_files()")
171214
logging.info(f"VGID: {self.osi.vgid}")
@@ -247,12 +290,11 @@ def install_files(self, cur_os):
247290
p_progress("Setting up Preboot volume...")
248291
logging.info("Setting up Preboot volume")
249292

250-
pb_vgid = os.path.join(self.osi.preboot, self.osi.vgid)
251-
os.makedirs(pb_vgid, exist_ok=True)
293+
os.makedirs(self.pb_vgid, exist_ok=True)
252294

253295
bless2 = bootcaches["bless2"]
254296

255-
restore_bundle = os.path.join(pb_vgid, bless2["RestoreBundlePath"])
297+
restore_bundle = os.path.join(self.pb_vgid, bless2["RestoreBundlePath"])
256298
os.makedirs(restore_bundle, exist_ok=True)
257299
restore_manifest = os.path.join(restore_bundle, "BuildManifest.plist")
258300
with open(restore_manifest, "wb") as fd:
@@ -292,25 +334,7 @@ def install_files(self, cur_os):
292334

293335
self.flush_progress()
294336

295-
os.makedirs(os.path.join(pb_vgid, "var/db"), exist_ok=True)
296-
admin_users = os.path.join(cur_os.preboot, cur_os.vgid, "var/db/AdminUserRecoveryInfo.plist")
297-
tg_admin_users = os.path.join(pb_vgid, "var/db/AdminUserRecoveryInfo.plist")
298-
if os.path.exists(tg_admin_users):
299-
self.chflags("noschg", tg_admin_users)
300-
shutil.copy(admin_users, tg_admin_users)
301-
302-
self.copy_idata.append((tg_admin_users, "AdminUserRecoveryInfo.plist"))
303-
304-
admin_users = plistlib.load(open(tg_admin_users, "rb"))
305-
self.stub_info["admin_users"] = {}
306-
for user, info in admin_users.items():
307-
self.stub_info["admin_users"][user] = {
308-
"uid": info["GeneratedUID"],
309-
"real_name": info["RealName"],
310-
}
311-
312-
# Stop macOS <12.0 bootability stufff from clobbering this file
313-
self.chflags("schg", tg_admin_users)
337+
self.copy_admin_users(cur_os)
314338

315339
# This is a workaround for some screwiness in the macOS <12.0 bootability
316340
# code, which ends up putting the apticket in the wrong volume...
@@ -438,12 +462,19 @@ def collect_firmware(self, pkg):
438462
logging.info("Detaching recovery ramdisk")
439463
subprocess.run(["hdiutil", "detach", "-quiet", "recovery"])
440464

441-
def collect_installer_data(self, path):
465+
def collect_installer_data(self, path, merge_stub_info=False):
442466
p_progress("Collecting installer data...")
443467
logging.info(f"Copying installer data to {path}")
444468

445469
for src, name in self.copy_idata:
446470
shutil.copy(src, os.path.join(path, name))
447471

472+
if merge_stub_info:
473+
with open(os.path.join(path, "stub_info.json"), "r") as fd:
474+
stub_info = json.load(fd)
475+
stub_info.update(self.stub_info)
476+
else:
477+
stub_info = self.stub_info
478+
448479
with open(os.path.join(path, "stub_info.json"), "w") as fd:
449-
json.dump(self.stub_info, fd)
480+
json.dump(stub_info, fd)

0 commit comments

Comments
 (0)