Skip to content

Commit 273c732

Browse files
author
Alexander Matveev
committed
8277493: [REDO] Quarantined jpackage apps are labeled as "damaged"
Reviewed-by: asemenyuk
1 parent 583a61a commit 273c732

File tree

4 files changed

+110
-95
lines changed

4 files changed

+110
-95
lines changed

src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java

Lines changed: 84 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -329,7 +329,8 @@ public void prepareApplicationFiles(Map<String, ? super Object> params)
329329
}
330330

331331
copyRuntimeFiles(params);
332-
sign(params);
332+
333+
doSigning(params);
333334
}
334335

335336
private void copyRuntimeFiles(Map<String, ? super Object> params)
@@ -355,7 +356,9 @@ private void copyRuntimeFiles(Map<String, ? super Object> params)
355356
}
356357
}
357358

358-
private void sign(Map<String, ? super Object> params) throws IOException {
359+
private void doSigning(Map<String, ? super Object> params)
360+
throws IOException {
361+
359362
if (Optional.ofNullable(
360363
SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
361364
try {
@@ -371,6 +374,12 @@ private void sign(Map<String, ? super Object> params) throws IOException {
371374
ENTITLEMENTS.fetchFrom(params));
372375
}
373376
restoreKeychainList(params);
377+
} else if (Platform.isArmMac()) {
378+
signAppBundle(params, root, "-", null, null);
379+
} else {
380+
// Calling signAppBundle() without signingIdentity will result in
381+
// unsigning app bundle
382+
signAppBundle(params, root, null, null, null);
374383
}
375384
}
376385

@@ -648,7 +657,40 @@ public static void restoreKeychainList(Map<String, ? super Object> params)
648657
IOUtils.exec(pb);
649658
}
650659

651-
static void signAppBundle(
660+
private static List<String> getCodesignArgs(
661+
boolean force, Path path, String signingIdentity,
662+
String identifierPrefix, Path entitlements, String keyChain) {
663+
List<String> args = new ArrayList<>();
664+
args.addAll(Arrays.asList("/usr/bin/codesign",
665+
"-s", signingIdentity,
666+
"-vvvv"));
667+
668+
if (!signingIdentity.equals("-")) {
669+
args.addAll(Arrays.asList("--timestamp",
670+
"--options", "runtime",
671+
"--prefix", identifierPrefix));
672+
if (keyChain != null && !keyChain.isEmpty()) {
673+
args.add("--keychain");
674+
args.add(keyChain);
675+
}
676+
if (Files.isExecutable(path)) {
677+
if (entitlements != null) {
678+
args.add("--entitlements");
679+
args.add(entitlements.toString());
680+
}
681+
}
682+
}
683+
684+
if (force) {
685+
args.add("--force");
686+
}
687+
688+
args.add(path.toString());
689+
690+
return args;
691+
}
692+
693+
private static void signAppBundle(
652694
Map<String, ? super Object> params, Path appLocation,
653695
String signingIdentity, String identifierPrefix, Path entitlements)
654696
throws IOException {
@@ -660,8 +702,8 @@ static void signAppBundle(
660702
try (Stream<Path> stream = Files.walk(appLocation)) {
661703
stream.peek(path -> { // fix permissions
662704
try {
663-
Set<PosixFilePermission> pfp =
664-
Files.getPosixFilePermissions(path);
705+
Set<PosixFilePermission> pfp
706+
= Files.getPosixFilePermissions(path);
665707
if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) {
666708
pfp = EnumSet.copyOf(pfp);
667709
pfp.add(PosixFilePermission.OWNER_WRITE);
@@ -670,13 +712,15 @@ static void signAppBundle(
670712
} catch (IOException e) {
671713
Log.verbose(e);
672714
}
673-
}).filter(p -> Files.isRegularFile(p) &&
674-
(Files.isExecutable(p) || p.toString().endsWith(".dylib"))
675-
&& !(p.toString().contains("dylib.dSYM/Contents"))
676-
&& !(p.toString().endsWith(appExecutable))
677-
).forEach(p -> {
715+
}).filter(p -> Files.isRegularFile(p)
716+
&& (Files.isExecutable(p) || p.toString().endsWith(".dylib"))
717+
&& !(p.toString().contains("dylib.dSYM/Contents"))
718+
&& !(p.toString().endsWith(appExecutable))
719+
).forEach(p -> {
678720
// noinspection ThrowableResultOfMethodCallIgnored
679-
if (toThrow.get() != null) return;
721+
if (toThrow.get() != null) {
722+
return;
723+
}
680724

681725
// If p is a symlink then skip the signing process.
682726
if (Files.isSymbolicLink(p)) {
@@ -695,42 +739,30 @@ static void signAppBundle(
695739
// run quietly
696740
IOUtils.exec(pb, false, null, false,
697741
Executor.INFINITE_TIMEOUT, true);
698-
Files.setPosixFilePermissions(p,oldPermissions);
742+
Files.setPosixFilePermissions(p, oldPermissions);
699743
} catch (IOException ioe) {
700744
Log.verbose(ioe);
701745
toThrow.set(ioe);
702746
return;
703747
}
704-
args = new ArrayList<>();
705-
args.addAll(Arrays.asList("/usr/bin/codesign",
706-
"--timestamp",
707-
"--options", "runtime",
708-
"-s", signingIdentity,
709-
"--prefix", identifierPrefix,
710-
"-vvvv"));
711-
if (keyChain != null && !keyChain.isEmpty()) {
712-
args.add("--keychain");
713-
args.add(keyChain);
714-
}
715-
if (Files.isExecutable(p)) {
716-
if (entitlements != null) {
717-
args.add("--entitlements");
718-
args.add(entitlements.toString());
748+
749+
// Sign only if we have identity
750+
if (signingIdentity != null) {
751+
args = getCodesignArgs(false, p, signingIdentity,
752+
identifierPrefix, entitlements, keyChain);
753+
try {
754+
Set<PosixFilePermission> oldPermissions
755+
= Files.getPosixFilePermissions(p);
756+
p.toFile().setWritable(true, true);
757+
ProcessBuilder pb = new ProcessBuilder(args);
758+
// run quietly
759+
IOUtils.exec(pb, false, null, false,
760+
Executor.INFINITE_TIMEOUT, true);
761+
Files.setPosixFilePermissions(p, oldPermissions);
762+
} catch (IOException ioe) {
763+
toThrow.set(ioe);
719764
}
720765
}
721-
args.add(p.toString());
722-
try {
723-
Set<PosixFilePermission> oldPermissions =
724-
Files.getPosixFilePermissions(p);
725-
p.toFile().setWritable(true, true);
726-
ProcessBuilder pb = new ProcessBuilder(args);
727-
// run quietly
728-
IOUtils.exec(pb, false, null, false,
729-
Executor.INFINITE_TIMEOUT, true);
730-
Files.setPosixFilePermissions(p, oldPermissions);
731-
} catch (IOException ioe) {
732-
toThrow.set(ioe);
733-
}
734766
}
735767
});
736768
}
@@ -739,31 +771,19 @@ static void signAppBundle(
739771
throw ioe;
740772
}
741773

774+
// We cannot continue signing without identity
775+
if (signingIdentity == null) {
776+
return;
777+
}
778+
742779
// sign all runtime and frameworks
743780
Consumer<? super Path> signIdentifiedByPList = path -> {
744781
//noinspection ThrowableResultOfMethodCallIgnored
745782
if (toThrow.get() != null) return;
746783

747784
try {
748-
List<String> args = new ArrayList<>();
749-
args.addAll(Arrays.asList("/usr/bin/codesign",
750-
"--timestamp",
751-
"--options", "runtime",
752-
"--force",
753-
"-s", signingIdentity, // sign with this key
754-
"--prefix", identifierPrefix,
755-
// use the identifier as a prefix
756-
"-vvvv"));
757-
758-
if (keyChain != null && !keyChain.isEmpty()) {
759-
args.add("--keychain");
760-
args.add(keyChain);
761-
}
762-
if (entitlements != null) {
763-
args.add("--entitlements");
764-
args.add(entitlements.toString());
765-
}
766-
args.add(path.toString());
785+
List<String> args = getCodesignArgs(true, path, signingIdentity,
786+
identifierPrefix, entitlements, keyChain);
767787
ProcessBuilder pb = new ProcessBuilder(args);
768788

769789
IOUtils.exec(pb);
@@ -794,29 +814,10 @@ static void signAppBundle(
794814
}
795815

796816
// sign the app itself
797-
List<String> args = new ArrayList<>();
798-
args.addAll(Arrays.asList("/usr/bin/codesign",
799-
"--timestamp",
800-
"--options", "runtime",
801-
"--force",
802-
"-s", signingIdentity,
803-
"--prefix", identifierPrefix,
804-
"-vvvv"));
805-
806-
if (keyChain != null && !keyChain.isEmpty()) {
807-
args.add("--keychain");
808-
args.add(keyChain);
809-
}
810-
811-
if (entitlements != null) {
812-
args.add("--entitlements");
813-
args.add(entitlements.toString());
814-
}
815-
816-
args.add(appLocation.toString());
817-
818-
ProcessBuilder pb =
819-
new ProcessBuilder(args.toArray(new String[args.size()]));
817+
List<String> args = getCodesignArgs(true, appLocation, signingIdentity,
818+
identifierPrefix, entitlements, keyChain);
819+
ProcessBuilder pb
820+
= new ProcessBuilder(args.toArray(new String[args.size()]));
820821

821822
IOUtils.exec(pb);
822823
}

test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,10 @@ public static boolean isOSX() {
178178
return (OS.contains("mac"));
179179
}
180180

181+
public static boolean isArmMac() {
182+
return (isOSX() && "aarch64".equals(System.getProperty("os.arch")));
183+
}
184+
181185
public static boolean isLinux() {
182186
return ((OS.contains("nix") || OS.contains("nux")));
183187
}

test/jdk/tools/jpackage/macosx/SigningAppImageTest.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,11 @@
2222
*/
2323

2424
import java.nio.file.Path;
25+
import java.util.List;
26+
2527
import jdk.jpackage.test.JPackageCommand;
2628
import jdk.jpackage.test.Annotations.Test;
29+
import jdk.jpackage.test.Annotations.Parameter;
2730
import jdk.jpackage.test.AdditionalLauncher;
2831

2932
/**
@@ -59,26 +62,31 @@
5962
public class SigningAppImageTest {
6063

6164
@Test
62-
public static void test() throws Exception {
65+
@Parameter("true")
66+
@Parameter("false")
67+
public void test(boolean doSign) throws Exception {
6368
SigningCheck.checkCertificates();
6469

6570
JPackageCommand cmd = JPackageCommand.helloAppImage();
66-
cmd.addArguments("--mac-sign", "--mac-signing-key-user-name",
67-
SigningBase.DEV_NAME, "--mac-signing-keychain",
68-
SigningBase.KEYCHAIN);
69-
71+
if (doSign) {
72+
cmd.addArguments("--mac-sign", "--mac-signing-key-user-name",
73+
SigningBase.DEV_NAME, "--mac-signing-keychain",
74+
SigningBase.KEYCHAIN);
75+
}
7076
AdditionalLauncher testAL = new AdditionalLauncher("testAL");
7177
testAL.applyTo(cmd);
7278
cmd.executeAndAssertHelloAppImageCreated();
7379

7480
Path launcherPath = cmd.appLauncherPath();
75-
SigningBase.verifyCodesign(launcherPath, true);
81+
SigningBase.verifyCodesign(launcherPath, doSign);
7682

7783
Path testALPath = launcherPath.getParent().resolve("testAL");
78-
SigningBase.verifyCodesign(testALPath, true);
84+
SigningBase.verifyCodesign(testALPath, doSign);
7985

8086
Path appImage = cmd.outputBundle();
81-
SigningBase.verifyCodesign(appImage, true);
82-
SigningBase.verifySpctl(appImage, "exec");
87+
SigningBase.verifyCodesign(appImage, doSign);
88+
if (doSign) {
89+
SigningBase.verifySpctl(appImage, "exec");
90+
}
8391
}
8492
}

test/jdk/tools/jpackage/share/AppContentTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -99,7 +99,9 @@ public void test() throws Exception {
9999
}
100100

101101
})
102-
.setExpectedExitCode(testPathArgs.contains(TEST_BAD) ? 1 : 0)
102+
// On macOS aarch64 we always signing app image and signing will fail, since
103+
// test produces invalid app bundle.
104+
.setExpectedExitCode(testPathArgs.contains(TEST_BAD) || TKit.isArmMac() ? 1 : 0)
103105
.run();
104106
}
105107
}

0 commit comments

Comments
 (0)