-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrated Spoon* code from Cuising to TinyFoundation
- Loading branch information
Showing
6 changed files
with
140 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...Foundation/Sources/HijackingHacks/empty.c → ...rces/HijackingHacks/HijackingHacksEmpty.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
// | ||
// empty.c | ||
// HijackingHacksEmpty.c | ||
// TinyFoundation | ||
// | ||
// Created by Serhii Mumriak on 11.01.2023 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// Spoon.c | ||
// Cuisine | ||
// | ||
// Created by Serhii Mumriak on 19.10.2023 | ||
// | ||
|
||
#include "Spoon.h" | ||
#include <unistd.h> | ||
|
||
int spoon(int (*_Nonnull child)(void *_Nullable info), void *_Nullable info) { | ||
int result = vfork(); | ||
|
||
if (result == 0) { | ||
// forked process | ||
int ret = child(info); | ||
// TODO: Handle the POSIX error here and propagate it to caller in future | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// | ||
// Spoon.h | ||
// Cuisine | ||
// | ||
// Created by Serhii Mumriak on 19.10.2023 | ||
// | ||
|
||
int spoon(int (*_Nonnull child)(void *_Nullable info), void *_Nullable info); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
TinyFoundation/Sources/TinyFoundation/Process/SpoonProcess.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// | ||
// SpoonProcess.swift | ||
// TinyFoundation | ||
// | ||
// Created by Serhii Mumriak on 19.10.2023 | ||
// | ||
|
||
import Spoon | ||
import SystemPackage | ||
import LinuxSys | ||
import TinyFoundation | ||
import Foundation | ||
|
||
fileprivate struct ForkMetadata { | ||
// this stuff should be pre-allocated since we should not really do ANY allocations after forking due to the fact that vfork does not copy original process' memory. it's a very shady gray zone in memory management on OS side | ||
// essentially, the only thing allocated will be the stack for the `forkedCall` function call | ||
let executablePath: UnsafePointer<CChar> | ||
let arguments: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> | ||
let environment: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> | ||
let workDirectoryPath: UnsafePointer<CChar>? | ||
} | ||
|
||
fileprivate func forkedCall(info: UnsafeMutableRawPointer!) -> CInt { | ||
let metadata = info.assumingMemoryBound(to: ForkMetadata.self).pointee | ||
|
||
if let workDirectoryPath = metadata.workDirectoryPath { | ||
chdir(workDirectoryPath) | ||
} | ||
|
||
return execve(metadata.executablePath /* path */, | ||
metadata.arguments /* argv */, | ||
metadata.environment /* envp */ ) | ||
} | ||
|
||
public func spoonProcess(executablePath: FilePath, arguments: [String] = [], environment: [String: String]? = nil, workDirectoryPath: FilePath? = nil) throws -> CInt { | ||
let arguments = [executablePath.string] + arguments | ||
let environment = (environment ?? ProcessInfo.processInfo.environment).map { "\($0)=\($1)" } | ||
var metadata = ForkMetadata( | ||
executablePath: arguments[0].withCString { strdup($0) }, | ||
arguments: arguments.nullTerminatedArrayOfCStrings, | ||
environment: environment.nullTerminatedArrayOfCStrings, | ||
workDirectoryPath: workDirectoryPath?.withCString { strdup($0) } | ||
) | ||
|
||
let childID = spoon(forkedCall /* child */, | ||
&metadata /* info */ ) | ||
|
||
if childID == 0 { | ||
// we are in forked process, tho technically this code should never be executed unless something failed | ||
fatalError("Error happened while executing `forkedCall`. TODO: propagate errors properly") | ||
} | ||
|
||
defer { | ||
metadata.workDirectoryPath?.deallocate() | ||
|
||
for i in 0..<environment.count { | ||
(metadata.environment + i).pointee?.deallocate() | ||
} | ||
metadata.arguments.deinitialize(count: environment.count + 1) | ||
metadata.environment.deallocate() | ||
|
||
for i in 0..<arguments.count { | ||
(metadata.arguments + i).pointee?.deallocate() | ||
} | ||
metadata.arguments.deinitialize(count: arguments.count + 1) | ||
metadata.arguments.deallocate() | ||
|
||
metadata.executablePath.deallocate() | ||
} | ||
|
||
return childID | ||
} |