19 Commits

Author SHA1 Message Date
tomer doron baf9597d12 trap SIGSEGV, SIGBUS and SIGFPE by default, in addition to SIGILL (#58)
motivation: print crash trace on segmentation faults and other common failures beyond illegal instructions

changes:
* include SIGSEGV, SIGBUS and SIGFPE in the default signals trapped
* update and improve tests
2022-06-08 09:06:33 -07:00
Konrad `ktoso` Malawski 7ba397e50d Merge pull request #57 from Fabio1988/patch-1
exit after printing stacktrace #51
2022-04-06 10:45:57 +09:00
Fabio1988 ad485ae151 exit after printing stacktrace #51 2022-03-17 12:17:02 +01:00
tomer doron 662e436989 ci update (#56)
motivation: 5.6 is out

changes:
* use release version of 5.6
* add docker setup for 5.7 (using nightly for now)
2022-03-16 21:15:06 -07:00
Konrad `ktoso` Malawski 923624a26e Merge pull request #53 from swift-server/tomerd-patch-2
update CI setup with new versions of swift
2021-09-23 06:03:22 +09:00
tomer doron e2621e2fa1 Create docker-compose.2004.main.yaml
* add ci setup for nightly toolchain
2021-09-22 12:02:54 -07:00
tomer doron ea4824d488 Update Dockerfile
address jazzy install issues on older ubuntu versions
2021-09-22 12:00:46 -07:00
tomer doron f1db8bf93d update CI setup with new versions of swift
motivation: 5.5 release is available

changes: 
* add docker CI setup to for 5.5
2021-09-22 11:56:43 -07:00
tomer doron 99a6c79fc5 Update README.md (#50)
motivation: highlight the background for this library and incourage use via service-lifecycle 

changes: update readme to reflect these ideas
2021-07-28 16:13:56 -07:00
Johannes Weiss d3e04a9d4b Merge pull request #49 from weissi/jw-other-platforms
forgot other platforms
2021-07-16 19:50:16 +01:00
Johannes Weiss b3b195e0e6 forgot other platforms 2021-07-16 19:34:47 +01:00
Johannes Weiss e434780428 Merge pull request #48 from weissi/jw-signals
allow other signals
2021-07-15 21:24:11 +01:00
Johannes Weiss ceaaf36f0f allow other signals 2021-07-15 19:40:14 +01:00
Konrad `ktoso` Malawski bb3bd2357e Merge pull request #45 from swift-server/tomerd-patch-1
adopt SSWG security guidelines
2021-06-21 11:24:12 +09:00
tomer doron 5f7686a18b Merge branch 'main' into tomerd-patch-1 2021-06-11 09:13:34 -07:00
tomer doron d9655c7867 add 5.4 CI (#46)
motivation: 5.4 was released, add 5.4 CI

changes: add docker-compose setup for 5.4
2021-06-11 09:13:24 -07:00
tomer doron 84bcaad52f Update README.md 2021-06-08 10:38:03 -07:00
tomer doron 7152ac0033 adopt SSWG security guidelines
add SECURITY.md detailing the security process
2021-06-08 10:37:16 -07:00
tomer doron 54a65d6391 recent changes to support windows broke macos (#44)
motivation: unbreak macos

changes: make _stdlib_demangleName only available on macOS and Windows where it is fully supported
2021-04-20 11:04:11 -07:00
14 changed files with 254 additions and 20 deletions
+9
View File
@@ -2,8 +2,14 @@
This Swift package provides support for automatically printing crash backtraces of Swift programs.
The library is designed to fill a gap in backtraces support for Swift on non-Darwin platforms.
When this gap is closed at the language runtime level, this library will become redundant and be deprecated.
## Usage
When building web-services and daemons, direct usage of this library is discouraged.
Instead, use [swift-service-lifecycle](https://github.com/swift-server/swift-service-lifecycle) which helps manage the application lifecycle including setting up backtraces hooks when needed.
Add `https://github.com/swift-server/swift-backtrace.git` as a dependency in your `Package.swift`.
### Crash backtraces
@@ -25,6 +31,9 @@ $ swift build -c release -Xswiftc -g
When your app crashes, a stacktrace will be printed to `stderr`.
## Security
Please see [SECURITY.md](SECURITY.md) for details on the security process.
## Acknowledgements
+43
View File
@@ -0,0 +1,43 @@
# Security
This document specifies the security process for the Backtrace project.
## Disclosures
### Private Disclosure Process
The Backtrace maintainers ask that known and suspected vulnerabilities be
privately and responsibly disclosed by emailing
[sswg-security-reports@forums.swift.org](mailto:sswg-security-reports@forums.swift.org)
with the all the required detail.
**Do not file a public issue.**
#### When to report a vulnerability
* You think you have discovered a potential security vulnerability in Backtrace.
* You are unsure how a vulnerability affects Backtrace.
#### What happens next?
* A member of the team will acknowledge receipt of the report within 3
working days (United States). This may include a request for additional
information about reproducing the vulnerability.
* We will privately inform the Swift Server Work Group ([SSWG][sswg]) of the
vulnerability within 10 days of the report as per their [security
guidelines][sswg-security].
* Once we have identified a fix we may ask you to validate it. We aim to do this
within 30 days. In some cases this may not be possible, for example when the
vulnerability exists at the protocol level and the industry must coordinate on
the disclosure process.
* If a CVE number is required, one will be requested from [MITRE][mitre]
providing you with full credit for the discovery.
* We will decide on a planned release date and let you know when it is.
* Prior to release, we will inform major dependents that a security-related
patch is impending.
* Once the fix has been released we will publish a security advisory on GitHub
and in the Server → Security Updates category on the [Swift forums][swift-forums-sec].
[sswg]: https://github.com/swift-server/sswg
[sswg-security]: https://github.com/swift-server/sswg/blob/main/security/README.md
[swift-forums-sec]: https://forums.swift.org/c/server/security-updates/
[mitre]: https://cveform.mitre.org/
+23 -2
View File
@@ -61,10 +61,24 @@ private let errorCallback: CBacktraceErrorCallback? = {
}
}
private func printBacktrace(signal: CInt) {
_ = fputs("Received signal \(signal). Backtrace:\n", stderr)
backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil)
}
public enum Backtrace {
/// Install the backtrace handler on default signals: `SIGILL`, `SIGSEGV`, `SIGBUS`, `SIGFPE`.
public static func install() {
self.setupHandler(signal: SIGILL) { _ in
backtrace_full(state, /* skip */ 0, fullCallback, errorCallback, nil)
Backtrace.install(signals: [SIGILL, SIGSEGV, SIGBUS, SIGFPE])
}
/// Install the backtrace handler when any of `signals` happen.
public static func install(signals: [CInt]) {
for signal in signals {
self.setupHandler(signal: signal) { signal in
printBacktrace(signal: signal)
raise(signal)
}
}
}
@@ -109,6 +123,11 @@ public enum Backtrace {
#endif
}
@available(*, deprecated, message: "signal selection unavailable on Windows")
public static func install(signals: [CInt]) {
Backtrace.install()
}
public static func install() {
// Install a last-chance vectored exception handler to capture the error
// before the termination and report the stack trace. It is unlikely
@@ -246,6 +265,8 @@ public enum Backtrace {
public enum Backtrace {
public static func install() {}
public static func install(signals: [CInt]) {}
@available(*, deprecated, message: "This method will be removed in the next major version.")
public static func print() {}
}
+2
View File
@@ -23,6 +23,7 @@ import ucrt
#endif
#endif
#if os(Linux) || os(Windows)
@_silgen_name("swift_demangle")
public
func _stdlib_demangleImpl(
@@ -53,3 +54,4 @@ internal func _stdlib_demangleName(_ mangledName: String) -> String {
return mangledName
}
}
#endif
+23 -2
View File
@@ -13,7 +13,28 @@
//===----------------------------------------------------------------------===//
import Backtrace
#if canImport(Darwin)
import Darwin
#elseif os(Linux)
import Glibc
#endif
Backtrace.install()
func raiseSignal(_ signal: Int32) {
raise(signal)
}
let reason = CommandLine.arguments.count == 2 ? CommandLine.arguments[1] : "unknown"
Backtrace.install()
fatalError(reason)
switch reason.uppercased() {
case "SIGILL":
raiseSignal(SIGILL)
case "SIGSEGV":
raiseSignal(SIGSEGV)
case "SIGBUS":
raiseSignal(SIGBUS)
case "SIGFPE":
raiseSignal(SIGFPE)
default:
fatalError(reason)
}
@@ -25,7 +25,11 @@ import XCTest
extension BacktraceTests {
public static var allTests: [(String, (BacktraceTests) -> () throws -> Void)] {
return [
("testBacktrace", testBacktrace),
("testFatalError", testFatalError),
("testSIGILL", testSIGILL),
("testSIGSEGV", testSIGSEGV),
("testSIGBUS", testSIGBUS),
("testSIGFPE", testSIGFPE),
]
}
}
+66 -12
View File
@@ -15,22 +15,76 @@
import XCTest
public final class BacktraceTests: XCTestCase {
func testBacktrace() {
#if os(Linux)
func testFatalError() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
let expectedError = UUID().uuidString
let stderr = try runSample(reason: expectedError)
print(stderr)
XCTAssert(stderr.contains("Received signal 4. Backtrace:"))
XCTAssert(stderr.contains("Current stack trace:"), "expected stanard error to include backtrace")
XCTAssert(stderr.contains("Fatal error: \(expectedError)"), "expected stanard error to include error information")
}
func testSIGILL() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
let stderr = try runSample(reason: "SIGILL")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGILL). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func testSIGSEGV() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
let stderr = try runSample(reason: "SIGSEGV")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGSEGV). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func testSIGBUS() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
let stderr = try runSample(reason: "SIGBUS")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGBUS). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func testSIGFPE() throws {
#if !os(Linux)
try XCTSkipIf(true, "test is only supported on Linux")
#endif
let stderr = try runSample(reason: "SIGFPE")
print(stderr)
XCTAssert(stderr.contains("Received signal \(SIGFPE). Backtrace:"))
XCTAssert(stderr.contains("Sample.raiseSignal"))
}
func runSample(reason: String) throws -> String {
let pipe = Pipe()
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/swift")
process.arguments = ["run", "Sample", expectedError]
process.arguments = ["run", "Sample", reason]
process.standardError = pipe
XCTAssertNoThrow(try process.run())
if process.isRunning {
process.waitUntilExit()
}
let stderr = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
print(stderr)
XCTAssert(stderr.contains("Current stack trace:"), "expected stanard error to include backtrace")
XCTAssert(stderr.contains("Fatal error: \(expectedError)"), "expected stanard error to include error information")
#endif
try process.run()
process.waitUntilExit()
return String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) ?? ""
}
}
+4 -2
View File
@@ -17,8 +17,10 @@ RUN apt-get update && apt-get install -y wget
RUN apt-get update && apt-get install -y lsof dnsutils netcat-openbsd net-tools curl jq # used by integration tests
# ruby and jazzy for docs generation
RUN apt-get update && apt-get install -y ruby ruby-dev libsqlite3-dev
RUN if [ "${ubuntu_version}" != "xenial" ] ; then gem install jazzy --no-ri --no-rdoc ; fi
RUN apt-get update && apt-get install -y ruby ruby-dev libsqlite3-dev build-essential
# jazzy no longer works on older version of ubuntu as ruby is too old.
RUN if [ "${ubuntu_version}" = "focal" ] ; then echo "gem: --no-document" > ~/.gemrc ; fi
RUN if [ "${ubuntu_version}" = "focal" ] ; then gem install jazzy ; fi
# tools
RUN mkdir -p $HOME/.tools
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.4
build:
args:
ubuntu_version: "focal"
swift_version: "5.4"
test:
image: swift-linux-backtrace:20.04-5.4
shell:
image: swift-linux-backtrace:20.04-5.4
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.5
build:
args:
ubuntu_version: "focal"
swift_version: "5.5"
test:
image: swift-linux-backtrace:20.04-5.5
shell:
image: swift-linux-backtrace:20.04-5.5
+16
View File
@@ -0,0 +1,16 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.6
build:
args:
ubuntu_version: "focal"
swift_version: "5.6"
test:
image: swift-linux-backtrace:20.04-5.6
shell:
image: swift-linux-backtrace:20.04-5.6
+15
View File
@@ -0,0 +1,15 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-5.7
build:
args:
base_image: "swiftlang/swift:nightly-main-focal"
test:
image: swift-linux-backtrace:20.04-5.7
shell:
image: swift-linux-backtrace:20.04-5.7
+15
View File
@@ -0,0 +1,15 @@
version: "3"
services:
runtime-setup:
image: swift-linux-backtrace:20.04-main
build:
args:
base_image: "swiftlang/swift:nightly-main-focal"
test:
image: swift-linux-backtrace:20.04-main
shell:
image: swift-linux-backtrace:20.04-main
+1 -1
View File
@@ -34,4 +34,4 @@ services:
shell:
<<: *common
entrypoint: /bin/bash
entrypoint: /bin/bash -l