Skip to content

Commit

Permalink
8277493: [REDO] Quarantined jpackage apps are labeled as "damaged"
Browse files Browse the repository at this point in the history
Reviewed-by: asemenyuk
  • Loading branch information
Alexander Matveev committed May 13, 2022
1 parent 583a61a commit 273c732
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -329,7 +329,8 @@ public void prepareApplicationFiles(Map<String, ? super Object> params)
}

copyRuntimeFiles(params);
sign(params);

doSigning(params);
}

private void copyRuntimeFiles(Map<String, ? super Object> params)
Expand All @@ -355,7 +356,9 @@ private void copyRuntimeFiles(Map<String, ? super Object> params)
}
}

private void sign(Map<String, ? super Object> params) throws IOException {
private void doSigning(Map<String, ? super Object> params)
throws IOException {

if (Optional.ofNullable(
SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.TRUE)) {
try {
Expand All @@ -371,6 +374,12 @@ private void sign(Map<String, ? super Object> params) throws IOException {
ENTITLEMENTS.fetchFrom(params));
}
restoreKeychainList(params);
} else if (Platform.isArmMac()) {
signAppBundle(params, root, "-", null, null);
} else {
// Calling signAppBundle() without signingIdentity will result in
// unsigning app bundle
signAppBundle(params, root, null, null, null);
}
}

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

static void signAppBundle(
private static List<String> getCodesignArgs(
boolean force, Path path, String signingIdentity,
String identifierPrefix, Path entitlements, String keyChain) {
List<String> args = new ArrayList<>();
args.addAll(Arrays.asList("/usr/bin/codesign",
"-s", signingIdentity,
"-vvvv"));

if (!signingIdentity.equals("-")) {
args.addAll(Arrays.asList("--timestamp",
"--options", "runtime",
"--prefix", identifierPrefix));
if (keyChain != null && !keyChain.isEmpty()) {
args.add("--keychain");
args.add(keyChain);
}
if (Files.isExecutable(path)) {
if (entitlements != null) {
args.add("--entitlements");
args.add(entitlements.toString());
}
}
}

if (force) {
args.add("--force");
}

args.add(path.toString());

return args;
}

private static void signAppBundle(
Map<String, ? super Object> params, Path appLocation,
String signingIdentity, String identifierPrefix, Path entitlements)
throws IOException {
Expand All @@ -660,8 +702,8 @@ static void signAppBundle(
try (Stream<Path> stream = Files.walk(appLocation)) {
stream.peek(path -> { // fix permissions
try {
Set<PosixFilePermission> pfp =
Files.getPosixFilePermissions(path);
Set<PosixFilePermission> pfp
= Files.getPosixFilePermissions(path);
if (!pfp.contains(PosixFilePermission.OWNER_WRITE)) {
pfp = EnumSet.copyOf(pfp);
pfp.add(PosixFilePermission.OWNER_WRITE);
Expand All @@ -670,13 +712,15 @@ static void signAppBundle(
} catch (IOException e) {
Log.verbose(e);
}
}).filter(p -> Files.isRegularFile(p) &&
(Files.isExecutable(p) || p.toString().endsWith(".dylib"))
&& !(p.toString().contains("dylib.dSYM/Contents"))
&& !(p.toString().endsWith(appExecutable))
).forEach(p -> {
}).filter(p -> Files.isRegularFile(p)
&& (Files.isExecutable(p) || p.toString().endsWith(".dylib"))
&& !(p.toString().contains("dylib.dSYM/Contents"))
&& !(p.toString().endsWith(appExecutable))
).forEach(p -> {
// noinspection ThrowableResultOfMethodCallIgnored
if (toThrow.get() != null) return;
if (toThrow.get() != null) {
return;
}

// If p is a symlink then skip the signing process.
if (Files.isSymbolicLink(p)) {
Expand All @@ -695,42 +739,30 @@ static void signAppBundle(
// run quietly
IOUtils.exec(pb, false, null, false,
Executor.INFINITE_TIMEOUT, true);
Files.setPosixFilePermissions(p,oldPermissions);
Files.setPosixFilePermissions(p, oldPermissions);
} catch (IOException ioe) {
Log.verbose(ioe);
toThrow.set(ioe);
return;
}
args = new ArrayList<>();
args.addAll(Arrays.asList("/usr/bin/codesign",
"--timestamp",
"--options", "runtime",
"-s", signingIdentity,
"--prefix", identifierPrefix,
"-vvvv"));
if (keyChain != null && !keyChain.isEmpty()) {
args.add("--keychain");
args.add(keyChain);
}
if (Files.isExecutable(p)) {
if (entitlements != null) {
args.add("--entitlements");
args.add(entitlements.toString());

// Sign only if we have identity
if (signingIdentity != null) {
args = getCodesignArgs(false, p, signingIdentity,
identifierPrefix, entitlements, keyChain);
try {
Set<PosixFilePermission> oldPermissions
= Files.getPosixFilePermissions(p);
p.toFile().setWritable(true, true);
ProcessBuilder pb = new ProcessBuilder(args);
// run quietly
IOUtils.exec(pb, false, null, false,
Executor.INFINITE_TIMEOUT, true);
Files.setPosixFilePermissions(p, oldPermissions);
} catch (IOException ioe) {
toThrow.set(ioe);
}
}
args.add(p.toString());
try {
Set<PosixFilePermission> oldPermissions =
Files.getPosixFilePermissions(p);
p.toFile().setWritable(true, true);
ProcessBuilder pb = new ProcessBuilder(args);
// run quietly
IOUtils.exec(pb, false, null, false,
Executor.INFINITE_TIMEOUT, true);
Files.setPosixFilePermissions(p, oldPermissions);
} catch (IOException ioe) {
toThrow.set(ioe);
}
}
});
}
Expand All @@ -739,31 +771,19 @@ static void signAppBundle(
throw ioe;
}

// We cannot continue signing without identity
if (signingIdentity == null) {
return;
}

// sign all runtime and frameworks
Consumer<? super Path> signIdentifiedByPList = path -> {
//noinspection ThrowableResultOfMethodCallIgnored
if (toThrow.get() != null) return;

try {
List<String> args = new ArrayList<>();
args.addAll(Arrays.asList("/usr/bin/codesign",
"--timestamp",
"--options", "runtime",
"--force",
"-s", signingIdentity, // sign with this key
"--prefix", identifierPrefix,
// use the identifier as a prefix
"-vvvv"));

if (keyChain != null && !keyChain.isEmpty()) {
args.add("--keychain");
args.add(keyChain);
}
if (entitlements != null) {
args.add("--entitlements");
args.add(entitlements.toString());
}
args.add(path.toString());
List<String> args = getCodesignArgs(true, path, signingIdentity,
identifierPrefix, entitlements, keyChain);
ProcessBuilder pb = new ProcessBuilder(args);

IOUtils.exec(pb);
Expand Down Expand Up @@ -794,29 +814,10 @@ static void signAppBundle(
}

// sign the app itself
List<String> args = new ArrayList<>();
args.addAll(Arrays.asList("/usr/bin/codesign",
"--timestamp",
"--options", "runtime",
"--force",
"-s", signingIdentity,
"--prefix", identifierPrefix,
"-vvvv"));

if (keyChain != null && !keyChain.isEmpty()) {
args.add("--keychain");
args.add(keyChain);
}

if (entitlements != null) {
args.add("--entitlements");
args.add(entitlements.toString());
}

args.add(appLocation.toString());

ProcessBuilder pb =
new ProcessBuilder(args.toArray(new String[args.size()]));
List<String> args = getCodesignArgs(true, appLocation, signingIdentity,
identifierPrefix, entitlements, keyChain);
ProcessBuilder pb
= new ProcessBuilder(args.toArray(new String[args.size()]));

IOUtils.exec(pb);
}
Expand Down
4 changes: 4 additions & 0 deletions test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ public static boolean isOSX() {
return (OS.contains("mac"));
}

public static boolean isArmMac() {
return (isOSX() && "aarch64".equals(System.getProperty("os.arch")));
}

public static boolean isLinux() {
return ((OS.contains("nix") || OS.contains("nux")));
}
Expand Down
28 changes: 18 additions & 10 deletions test/jdk/tools/jpackage/macosx/SigningAppImageTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -22,8 +22,11 @@
*/

import java.nio.file.Path;
import java.util.List;

import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Annotations.Parameter;
import jdk.jpackage.test.AdditionalLauncher;

/**
Expand Down Expand Up @@ -59,26 +62,31 @@
public class SigningAppImageTest {

@Test
public static void test() throws Exception {
@Parameter("true")
@Parameter("false")
public void test(boolean doSign) throws Exception {
SigningCheck.checkCertificates();

JPackageCommand cmd = JPackageCommand.helloAppImage();
cmd.addArguments("--mac-sign", "--mac-signing-key-user-name",
SigningBase.DEV_NAME, "--mac-signing-keychain",
SigningBase.KEYCHAIN);

if (doSign) {
cmd.addArguments("--mac-sign", "--mac-signing-key-user-name",
SigningBase.DEV_NAME, "--mac-signing-keychain",
SigningBase.KEYCHAIN);
}
AdditionalLauncher testAL = new AdditionalLauncher("testAL");
testAL.applyTo(cmd);
cmd.executeAndAssertHelloAppImageCreated();

Path launcherPath = cmd.appLauncherPath();
SigningBase.verifyCodesign(launcherPath, true);
SigningBase.verifyCodesign(launcherPath, doSign);

Path testALPath = launcherPath.getParent().resolve("testAL");
SigningBase.verifyCodesign(testALPath, true);
SigningBase.verifyCodesign(testALPath, doSign);

Path appImage = cmd.outputBundle();
SigningBase.verifyCodesign(appImage, true);
SigningBase.verifySpctl(appImage, "exec");
SigningBase.verifyCodesign(appImage, doSign);
if (doSign) {
SigningBase.verifySpctl(appImage, "exec");
}
}
}
6 changes: 4 additions & 2 deletions test/jdk/tools/jpackage/share/AppContentTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -99,7 +99,9 @@ public void test() throws Exception {
}

})
.setExpectedExitCode(testPathArgs.contains(TEST_BAD) ? 1 : 0)
// On macOS aarch64 we always signing app image and signing will fail, since
// test produces invalid app bundle.
.setExpectedExitCode(testPathArgs.contains(TEST_BAD) || TKit.isArmMac() ? 1 : 0)
.run();
}
}

1 comment on commit 273c732

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.