test: compare native keychain deletion timing
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
# Deferring native keychain deletion did not prevent inventory growth
|
||||
|
||||
The fixed paired diagnostic reproduced the same `Security::AppleDatabase`
|
||||
inventory in both measured processes: **1 → 2 → 201 → 201**. Deferring native
|
||||
`SecKeychainDelete` and the initial keychain `CFRelease` until after all observed
|
||||
returned item, key, data, error and copy owners were released did not prevent the
|
||||
increase on this pinned native bridge path. This rules out changing only that
|
||||
observed deletion timing as a remedy in this control. It does not identify
|
||||
bridge-internal or Apple ownership, establish whether any unobserved native
|
||||
references remain, or assign a platform defect.
|
||||
|
||||
The two arms used the same fresh private RSA seed, same measured C binary and
|
||||
installed native bridge, and separate processes. The fixed normal arm ran first
|
||||
and reproduced [attempt B](NATIVE_IMPORT.md), whose source and receipts remain
|
||||
unchanged. The deferred arm ran next. There was one paired execution, 200
|
||||
operations per arm, with no retry, count change, reversed order or managed caller
|
||||
in either measured child. These are bounded diagnostics on macOS **26.5.2** build
|
||||
**25F84** arm64. No production mitigation, RSS budget decision, full-soak/G4 pass
|
||||
or #799 closure follows.
|
||||
|
||||
## What changed between the arms
|
||||
|
||||
Both arms ran the same pinned native imports, nine ordered wrapper keychain
|
||||
copies per operation, and item, copy and legacy-key release sequence. The logical
|
||||
registry retired at the same point in all **400** operations: the final copied
|
||||
certificate Untrack after original certificate disposal and initial import-state
|
||||
logical release. At logical zero there were five observed returned references:
|
||||
the initial keychain, current keychain copy, copied certificate, identity and
|
||||
legacy key. The original certificate reference was already released.
|
||||
|
||||
| Arm | Actual native delete and initial release | Observed returned CF owners at delete |
|
||||
|---|---|---:|
|
||||
| Normal | At logical zero, during copied certificate Untrack | 5: initial keychain and four other references |
|
||||
| Deferred | After all item, copy and legacy-key releases | 1: initial keychain only |
|
||||
|
||||
In the deferred arm the initial native owner stayed held after the logical
|
||||
registry retired; its delete and `CFRelease` ran only after all other observed
|
||||
returned owners were gone. The collector replayed every logical owner transition
|
||||
and independently verified the physical keychain owner and actual deletion state.
|
||||
This ledger covers references returned to the child. It does not enumerate
|
||||
unobservable references within the installed bridge or Security.framework.
|
||||
|
||||
All **200** keychain deletes in each arm returned native status zero. All bridge
|
||||
operations that use one as success returned one; the reached OSStatus fields
|
||||
were zero. Each arm observed **1,800** keychain copy calls with normalized status
|
||||
zero and **800** returned private associations. The four associated copy stages
|
||||
were identical: post-move original certificate Track, copied certificate Track,
|
||||
original certificate Untrack and copied certificate Untrack. Both identity calls
|
||||
returned null with success. Each arm balanced **2,402/2,402** returned CF owners,
|
||||
including **200/200** initial keychain refs, with zero remaining logical owners
|
||||
and no fallback cleanup. First and last certificate identity checks matched the
|
||||
one unchanged shared seed in both arms.
|
||||
|
||||
## Native measurements and cleanup
|
||||
|
||||
| Arm | Checkpoint | AppleDatabase count / shallow bytes | Numeric FDs | Owned keychain files / FDs | RSS bytes |
|
||||
|---|---|---:|---:|---:|---:|
|
||||
| Normal | Before | 1 / 768 | 3 | 0 / 0 | 7,667,712 |
|
||||
| Normal | First | 2 / 1,536 | 3 | 0 / 0 | 10,895,360 |
|
||||
| Normal | 200 | 201 / 154,368 | 3 | 0 / 0 | 14,548,992 |
|
||||
| Normal | Five-second idle | 201 / 154,368 | 3 | 0 / 0 | 14,581,760 |
|
||||
| Deferred | Before | 1 / 768 | 3 | 0 / 0 | 7,536,640 |
|
||||
| Deferred | First | 2 / 1,536 | 3 | 0 / 0 | 10,878,976 |
|
||||
| Deferred | 200 | 201 / 154,368 | 3 | 0 / 0 | 14,123,008 |
|
||||
| Deferred | Five-second idle | 201 / 154,368 | 3 | 0 / 0 | 14,139,392 |
|
||||
|
||||
Native child times were **17.403** and **17.290** seconds, respectively. Parent
|
||||
wall including the seed and both arms was **35.545 seconds**. Heap inventory
|
||||
came from `heap --noContent -s`; RSS was Mach task resident size. Numeric FD
|
||||
counts did not rise. A classified native heap object is not an open handle and
|
||||
its shallow bytes do not explain the full RSS change. The one fixed-order pair
|
||||
does not estimate a timing effect on RSS or generalize beyond this control.
|
||||
|
||||
The single .NET **10.0.14** SDK **2.0.1** seed ran outside both measured children.
|
||||
Its private DER/PKCS1 fixture files were mode 0600 in a private root, and its
|
||||
SDK PKI was removed after seed exit. Both measured children read the same seed
|
||||
files; the public leaf hash and private file identity metadata remained stable.
|
||||
The native children checked the pinned bridge image and rejected CLR/SDK images.
|
||||
No PFX parser or managed finalizer behavior was emulated. The explicit legacy
|
||||
key release order was unchanged between the arms.
|
||||
|
||||
All four read-only default/search-list fingerprints matched; all query statuses
|
||||
were zero and the search-list count was two. No setter or restore API ran.
|
||||
Both builds, seed and both measured children exited zero and were reaped. Both
|
||||
owned keychain directories already had zero keychain files before harness
|
||||
cleanup. The remaining private fixture files were overwritten and unlinked
|
||||
only after all reaping, and the private root was removed. No physical secure
|
||||
erasure guarantee is claimed. Native compilation emitted **six unsuppressed
|
||||
deprecation warnings** for the exercised public keychain APIs; the seed build
|
||||
reported zero warnings and errors.
|
||||
|
||||
The result narrows the remaining question: the installed native bridge plus
|
||||
Security.framework import path retained the database inventory with both tested
|
||||
release orders, while the [empty keychain control](PURE_APPLE.md) did not. It
|
||||
remains unresolved which native component owns the retained objects. There is no
|
||||
supported application-only correction demonstrated by this experiment.
|
||||
|
||||
## Pinned evidence
|
||||
|
||||
Raw private output is `/tmp/opcua2-native-import-timing-20261110a`.
|
||||
[Selected receipts](evidence/2026-11-10-native-import-timing/verification.json)
|
||||
retain the source/runtime/binary hashes, build logs, shared seed and cleanup
|
||||
receipts, both arm summaries and nine exact raw JSONL rows per arm. The 207 raw
|
||||
rows per arm and all native heap/FD snapshots stay local and are hash-bound.
|
||||
|
||||
- Pair result SHA-256: `f0b4195fe445259934b91e9c6743437c8427844b8fe5e3a9aafe28847f495986`
|
||||
- Normal raw JSONL SHA-256: `73288755c768065ad0a8b2dad6964696d707f1c6be5a6b8bd531902cb3b4bf51`
|
||||
- Deferred raw JSONL SHA-256: `61691ff4c500d2696f6998cd225d19677a0cb8eb47ed8f7545b01f76e4acc456`
|
||||
- Measured binary SHA-256: `cec035355aea998d6dd9311561b23e1617a1096191847cf99f1a0a90a7b6d112`
|
||||
- Seed DLL SHA-256: `36e648ac37b61cb5dd65f03dcf5db555fc297d23243c42e282ef522f15a8a7a1`
|
||||
|
||||
The fixed collector accepts only the pinned source and binary set and a fresh
|
||||
private output. Any further run needs its own scope and serialization review.
|
||||
|
||||
```sh
|
||||
PYTHONDONTWRITEBYTECODE=1 python3 \
|
||||
scripts/validation/opcua-lifecycle-memory/native-retention/native_import_timing.py \
|
||||
--references /tmp/opcua2-native-reload-20261110a/bin/Release/net10.0 \
|
||||
--output /tmp/opcua2-native-import-timing-FRESH
|
||||
```
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
// Paired timing diagnostic, derived from the immutable completed native bridge control.
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#include <mach/mach.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define REPETITIONS 200
|
||||
static char root[PATH_MAX],seed_root[PATH_MAX];
|
||||
static const char *arm_order;
|
||||
static int defer_delete;
|
||||
static struct timespec started;
|
||||
static unsigned created_refs, released_refs, query_releases;
|
||||
static double elapsed(void) {
|
||||
struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return (double)(now.tv_sec-started.tv_sec)+(double)(now.tv_nsec-started.tv_nsec)/1e9;
|
||||
}
|
||||
static void die(const char *message) {
|
||||
fprintf(stdout,"{\"kind\":\"failed\",\"message\":\"%s\",\"createdRefs\":%u,\"releasedRefs\":%u,\"elapsedSeconds\":%.6f}\n",message,created_refs,released_refs,elapsed());
|
||||
fflush(stdout); exit(1);
|
||||
}
|
||||
static void hex(const unsigned char *bytes, size_t length, char *out) {
|
||||
const char *alphabet="0123456789abcdef";
|
||||
for(size_t i=0;i<length;i++){out[i*2]=alphabet[bytes[i]>>4];out[i*2+1]=alphabet[bytes[i]&15];}
|
||||
out[length*2]=0;
|
||||
}
|
||||
static void wipe(void *memory, size_t length) {
|
||||
volatile unsigned char *bytes=(volatile unsigned char *)memory;
|
||||
while(length--)*bytes++=0;
|
||||
}
|
||||
static OSStatus keychain_path(SecKeychainRef keychain, char *path) {
|
||||
if(!keychain||CFGetTypeID(keychain)!=SecKeychainGetTypeID())return errSecParam;
|
||||
UInt32 length=PATH_MAX-1;
|
||||
OSStatus status=SecKeychainGetPath(keychain,&length,path);
|
||||
if(status==errSecSuccess && length<PATH_MAX)path[length]=0;
|
||||
return status;
|
||||
}
|
||||
struct fingerprint { char default_sha[65], search_sha[65]; CFIndex search_count; };
|
||||
static struct fingerprint fingerprint(const char *stage) {
|
||||
SecKeychainRef default_keychain=NULL;
|
||||
CFArrayRef search=NULL;
|
||||
struct fingerprint out; memset(&out,0,sizeof(out));
|
||||
char path[PATH_MAX]; memset(path,0,sizeof(path));
|
||||
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
||||
OSStatus default_status=SecKeychainCopyDefault(&default_keychain);
|
||||
OSStatus default_path_status=default_keychain?keychain_path(default_keychain,path):errSecInvalidKeychain;
|
||||
if(default_status==errSecSuccess && default_path_status==errSecSuccess){CC_SHA256(path,(CC_LONG)strlen(path),digest);hex(digest,sizeof(digest),out.default_sha);}
|
||||
if(default_keychain){CFRelease(default_keychain);query_releases++;default_keychain=NULL;}
|
||||
OSStatus search_status=SecKeychainCopySearchList(&search);
|
||||
OSStatus search_path_status=errSecSuccess;
|
||||
CC_SHA256_CTX hash; CC_SHA256_Init(&hash);
|
||||
if(!search||CFGetTypeID(search)!=CFArrayGetTypeID())search_path_status=errSecParam;
|
||||
if(search_status==errSecSuccess && search && search_path_status==errSecSuccess){
|
||||
out.search_count=CFArrayGetCount(search);
|
||||
uint64_t count=(uint64_t)out.search_count; CC_SHA256_Update(&hash,&count,sizeof(count));
|
||||
for(CFIndex i=0;i<out.search_count;i++){
|
||||
// CFArray values are borrowed. Releasing the owned array balances its element references.
|
||||
SecKeychainRef borrowed=(SecKeychainRef)CFArrayGetValueAtIndex(search,i);
|
||||
memset(path,0,sizeof(path)); OSStatus status=keychain_path(borrowed,path);
|
||||
if(status!=errSecSuccess){search_path_status=status;break;}
|
||||
uint32_t length=(uint32_t)strlen(path);CC_SHA256_Update(&hash,&length,sizeof(length));CC_SHA256_Update(&hash,path,length);
|
||||
}
|
||||
}
|
||||
CC_SHA256_Final(digest,&hash);hex(digest,sizeof(digest),out.search_sha);
|
||||
if(search){CFRelease(search);query_releases++;search=NULL;}
|
||||
fprintf(stdout,"{\"kind\":\"fingerprint\",\"stage\":\"%s\",\"defaultStatus\":%d,\"defaultPathStatus\":%d,\"searchStatus\":%d,\"searchPathStatus\":%d,\"defaultSha256\":\"%s\",\"searchSha256\":\"%s\",\"searchCount\":%ld,\"ownedQueryReferencesReleased\":%u}\n",stage,(int)default_status,(int)default_path_status,(int)search_status,(int)search_path_status,out.default_sha,out.search_sha,(long)out.search_count,query_releases);fflush(stdout);
|
||||
if(default_status || default_path_status || search_status || search_path_status)die("Read-only keychain fingerprint failed");
|
||||
return out;
|
||||
}
|
||||
static void checkpoint(const char *stage, unsigned operations) {
|
||||
struct mach_task_basic_info info; mach_msg_type_number_t count=MACH_TASK_BASIC_INFO_COUNT;
|
||||
kern_return_t status=task_info(mach_task_self(),MACH_TASK_BASIC_INFO,(task_info_t)&info,&count);
|
||||
if(status!=KERN_SUCCESS)die("task_info failed");
|
||||
struct timespec wall;clock_gettime(CLOCK_REALTIME,&wall);struct tm utc;gmtime_r(&wall.tv_sec,&utc);
|
||||
char stamp[40];strftime(stamp,sizeof(stamp),"%Y-%m-%dT%H:%M:%S",&utc);
|
||||
fprintf(stdout,"{\"kind\":\"checkpoint\",\"mode\":\"native-bridge-import-timing\",\"order\":\"%s\",\"stage\":\"%s\",\"operations\":%u,\"processId\":%d,\"utc\":\"%s.%03ldZ\",\"elapsedSeconds\":%.6f,\"rssBytes\":%llu,\"createdRefs\":%u,\"releasedRefs\":%u,\"managedRuntimePresent\":false}\n",arm_order,stage,operations,getpid(),stamp,wall.tv_nsec/1000000,elapsed(),(unsigned long long)info.resident_size,created_refs,released_refs);fflush(stdout);
|
||||
char next[PATH_MAX];int n=snprintf(next,sizeof(next),"%s/continue-%s",root,stage);if(n<0 || (size_t)n>=sizeof(next))die("Checkpoint path overflow");
|
||||
while(access(next,F_OK)!=0){if(elapsed()>180)die("Checkpoint deadline exceeded");struct timespec pause={0,25000000};nanosleep(&pause,NULL);}
|
||||
}
|
||||
static int absent(const char *path){struct stat state;if(lstat(path,&state)==0)return 0;return errno==ENOENT;}
|
||||
|
||||
#define BRIDGE_SHA "0333994e217a3d111d36d7f31460eea69a286f9fc819e2d7c746df13d2aec46c"
|
||||
static int32_t (*import_cert)(const uint8_t*,int32_t,int32_t,CFStringRef,SecKeychainRef,int32_t,SecCertificateRef*,SecIdentityRef*,int32_t*);
|
||||
static int32_t (*create_key)(const uint8_t*,int32_t,uint32_t,int32_t,SecKeyRef*,CFErrorRef*);
|
||||
static SecKeyRef (*copy_public)(SecKeyRef);
|
||||
static int32_t (*external_key)(SecKeyRef,CFDataRef*,CFErrorRef*);
|
||||
static int32_t (*create_chain)(const char*,int32_t,const uint8_t*,SecKeychainRef*);
|
||||
static int32_t (*never_lock)(SecKeychainRef);
|
||||
static int32_t (*import_key)(const uint8_t*,int32_t,int32_t,SecKeyRef*,int32_t*);
|
||||
static int32_t (*move_key)(SecCertificateRef,SecKeychainRef,SecKeyRef,SecIdentityRef*,int32_t*);
|
||||
static int32_t (*copy_cert)(SecIdentityRef,SecCertificateRef*);
|
||||
static int32_t (*copy_chain)(CFTypeRef,SecKeychainRef*);
|
||||
static int32_t (*delete_chain)(SecKeychainRef);
|
||||
static unsigned all_created,all_released;
|
||||
static void owned(CFTypeRef value){if(value)all_created++;}
|
||||
static void drop(CFTypeRef *value){if(*value){CFRelease(*value);*value=NULL;all_released++;}}
|
||||
#define DROP(value) drop((CFTypeRef*)&(value))
|
||||
static void image_guard(void){
|
||||
unsigned bridge_images=0;
|
||||
for(uint32_t i=0;i<_dyld_image_count();i++){
|
||||
const char *name=_dyld_get_image_name(i);
|
||||
if(strstr(name,"libcoreclr")||strstr(name,"libhostfxr")||strstr(name,"Opc.Ua"))die("Measured child loaded a managed runtime or SDK");
|
||||
if(strstr(name,"libSystem.Security.Cryptography.Native.Apple.dylib"))bridge_images++;
|
||||
}
|
||||
if(bridge_images!=1)die("Expected exactly one pinned native bridge image");
|
||||
}
|
||||
static void load_bridge(const char *path){
|
||||
FILE *file=fopen(path,"rb");if(!file)die("Pinned bridge could not be read");
|
||||
CC_SHA256_CTX hash;CC_SHA256_Init(&hash);unsigned char bytes[8192],digest[32];size_t size;
|
||||
while((size=fread(bytes,1,sizeof(bytes),file)))CC_SHA256_Update(&hash,bytes,(CC_LONG)size);
|
||||
int bad=ferror(file);fclose(file);if(bad)die("Pinned bridge read failed");CC_SHA256_Final(digest,&hash);
|
||||
char actual[65];hex(digest,sizeof(digest),actual);if(strcmp(actual,BRIDGE_SHA))die("Pinned bridge hash changed");
|
||||
void *library=dlopen(path,RTLD_NOW|RTLD_LOCAL);if(!library)die("Pinned bridge load failed");
|
||||
#define LOAD(variable,symbol) do { *(void**)(&variable)=dlsym(library,symbol); if(!variable)die("Pinned bridge export missing"); Dl_info info;char loaded[PATH_MAX],expected[PATH_MAX];if(!dladdr((void*)variable,&info)||!realpath(info.dli_fname,loaded)||!realpath(path,expected)||strcmp(loaded,expected))die("Bridge export image identity changed"); } while(0)
|
||||
LOAD(import_cert,"AppleCryptoNative_X509ImportCertificate");LOAD(create_key,"AppleCryptoNative_SecKeyCreateWithData");
|
||||
LOAD(copy_public,"AppleCryptoNative_SecKeyCopyPublicKey");LOAD(external_key,"AppleCryptoNative_SecKeyCopyExternalRepresentation");
|
||||
LOAD(create_chain,"AppleCryptoNative_SecKeychainCreate");LOAD(never_lock,"AppleCryptoNative_SetKeychainNeverLock");
|
||||
LOAD(import_key,"AppleCryptoNative_SecKeyImportEphemeral");LOAD(move_key,"AppleCryptoNative_X509MoveToKeychain");
|
||||
LOAD(copy_cert,"AppleCryptoNative_X509CopyCertFromIdentity");LOAD(copy_chain,"AppleCryptoNative_SecKeychainItemCopyKeychain");
|
||||
LOAD(delete_chain,"AppleCryptoNative_SecKeychainDelete");
|
||||
#undef LOAD
|
||||
image_guard();
|
||||
}
|
||||
struct copy_result {
|
||||
const char *stage,*action;int32_t status;int present,associated;
|
||||
unsigned owners_before,owners_after;
|
||||
int registry_before,registry_after,native_owner_before,native_owner_after;
|
||||
};
|
||||
struct operation_state {
|
||||
SecCertificateRef cert,copied;SecIdentityRef identity;SecKeyRef modern,public_key,legacy;
|
||||
CFDataRef external;SecKeychainRef keychain,keychain_identity,outer;CFErrorRef error;
|
||||
char path[PATH_MAX],backing[PATH_MAX];
|
||||
unsigned logical_owners;int initial_owner,registry_active,pending_delete,cert_tracked,copied_tracked,identity_tracked;
|
||||
int failed,path_verified,deleted,fallback_cleanup,import_state_released,leaf_checked,leaf_matches;
|
||||
unsigned import_owners_before,import_owners_after;
|
||||
struct ownership_observation {
|
||||
const char *stage;
|
||||
int copy_live,cert_live,copied_live,identity_live,legacy_live;
|
||||
unsigned owned_outputs_remaining;
|
||||
} zero, deletion;
|
||||
int32_t cert_return,cert_status,modern_return,create_status,lock_status,external_return,key_return,key_status,move_return,move_status,copy_cert_status,delete_status,path_status;
|
||||
CFIndex modern_error,external_error;int modern_error_present,external_error_present;unsigned copy_count;
|
||||
struct copy_result copies[16];
|
||||
};
|
||||
static int private_path(struct operation_state *s,SecKeychainRef keychain){
|
||||
if(!keychain||CFGetTypeID(keychain)!=SecKeychainGetTypeID())return 0;
|
||||
char actual[PATH_MAX];memset(actual,0,sizeof(actual));int32_t status=keychain_path(keychain,actual);
|
||||
return status==0 && (!strcmp(actual,s->path)||!strcmp(actual,s->backing));
|
||||
}
|
||||
static struct ownership_observation observe(const struct operation_state *s,const char *stage,int copy_live){
|
||||
return (struct ownership_observation){stage,copy_live,s->cert!=NULL,s->copied!=NULL,s->identity!=NULL,s->legacy!=NULL,
|
||||
all_created-all_released};
|
||||
}
|
||||
static void delete_owner(struct operation_state *s,const char *stage,int copy_live){
|
||||
if(!s->keychain)return;
|
||||
if(s->deleted){s->failed=1;return;}
|
||||
s->deletion=observe(s,stage,copy_live);
|
||||
s->path_verified=private_path(s,s->keychain);
|
||||
if(s->path_verified){s->delete_status=delete_chain(s->keychain);s->deleted=1;}
|
||||
if(!s->path_verified||s->delete_status)s->failed=1;
|
||||
DROP(s->keychain);released_refs++;
|
||||
}
|
||||
static void relinquish(struct operation_state *s,const char *stage,int copy_live){
|
||||
if(!s->logical_owners){s->failed=1;return;}
|
||||
if(--s->logical_owners==0){
|
||||
s->registry_active=0; // Logical removal happens at the same point in both arms.
|
||||
s->zero=observe(s,stage,copy_live);
|
||||
if(defer_delete)s->pending_delete=1;
|
||||
else delete_owner(s,stage,copy_live);
|
||||
}
|
||||
}
|
||||
static SecKeychainRef copied_chain(struct operation_state *s,CFTypeRef item,const char *stage,int *associated){
|
||||
*associated=0;if(!item)return NULL;
|
||||
CFTypeID type=CFGetTypeID(item);if(type!=SecCertificateGetTypeID()&&type!=SecIdentityGetTypeID()){s->failed=1;return NULL;}
|
||||
SecKeychainRef result=NULL;int32_t status=copy_chain(item,&result);owned(result);
|
||||
int type_ok=!result||CFGetTypeID(result)==SecKeychainGetTypeID();
|
||||
int belongs=result&&type_ok&&s->keychain_identity==result&&private_path(s,result);
|
||||
if(s->copy_count<16)s->copies[s->copy_count++]=(struct copy_result){stage,"lookup",status,result!=NULL,belongs,
|
||||
s->logical_owners,s->logical_owners,s->registry_active,s->registry_active,s->keychain!=NULL,s->keychain!=NULL};else s->failed=1;
|
||||
if(status || !type_ok || (result&&!belongs))s->failed=1;
|
||||
*associated=status==0&&belongs;return result;
|
||||
}
|
||||
static void record_copy_action(struct operation_state *s,unsigned index,const char *action){
|
||||
if(s->copy_count==index+1){struct copy_result *copy=&s->copies[index];copy->action=action;
|
||||
copy->owners_after=s->logical_owners;copy->registry_after=s->registry_active;copy->native_owner_after=s->keychain!=NULL;}
|
||||
}
|
||||
static void track(struct operation_state *s,CFTypeRef item,const char *stage,int *tracked){
|
||||
unsigned index=s->copy_count;int associated=0;SecKeychainRef copy=copied_chain(s,item,stage,&associated);
|
||||
// Installed TrackItem does nothing for a null copy; never invent an owner.
|
||||
if(associated){if(*tracked||!s->registry_active)s->failed=1;else{s->logical_owners++;*tracked=1;}}
|
||||
record_copy_action(s,index,"track");DROP(copy);
|
||||
}
|
||||
static void untrack(struct operation_state *s,CFTypeRef item,const char *stage,int *tracked){
|
||||
if(!item)return;
|
||||
unsigned index=s->copy_count;int associated=0;SecKeychainRef copy=copied_chain(s,item,stage,&associated);
|
||||
if(*tracked){if(associated&&s->registry_active){*tracked=0;relinquish(s,stage,copy!=NULL);}else s->failed=1;}
|
||||
// A still-registered private keychain must never consume an untracked owner.
|
||||
// After logical retirement no registry entry remains, even if native deletion is deferred.
|
||||
else if(associated&&s->registry_active)s->failed=1;
|
||||
record_copy_action(s,index,"untrack");
|
||||
// Final logical-owner release above precedes this copy's CFRelease.
|
||||
DROP(copy);
|
||||
}
|
||||
static int leaf_equal(SecCertificateRef cert,const unsigned char *der,size_t length){
|
||||
CFDataRef data=SecCertificateCopyData(cert);owned(data);
|
||||
int equal=data&&CFGetTypeID(data)==CFDataGetTypeID()&&CFDataGetLength(data)==(CFIndex)length&&!memcmp(CFDataGetBytePtr(data),der,length);
|
||||
DROP(data);return equal;
|
||||
}
|
||||
static void import_operation(unsigned iteration,const unsigned char *der,size_t der_length,const unsigned char *key,size_t key_length){
|
||||
struct operation_state s;memset(&s,0,sizeof(s));
|
||||
s.cert_return=s.cert_status=s.modern_return=s.create_status=s.lock_status=s.external_return=s.key_return=s.key_status=s.move_return=s.move_status=s.copy_cert_status=s.delete_status=s.path_status=INT32_MIN;
|
||||
unsigned before_created=all_created,before_released=all_released;
|
||||
unsigned char random[144],password[129];char suffix[33];
|
||||
if(SecRandomCopyBytes(kSecRandomDefault,sizeof(random),random))die("Secure random failed");
|
||||
hex(random,16,suffix);const unsigned char choices[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@";
|
||||
for(unsigned i=0;i<128;i++)password[i]=choices[random[16+i]&63];password[128]=0;wipe(random,sizeof(random));
|
||||
int n=snprintf(s.path,sizeof(s.path),"%s/tmp/native-import-%s.keychain",root,suffix);
|
||||
if(n<0||(size_t)n>=sizeof(s.path))die("Private fixture path overflow");
|
||||
n=snprintf(s.backing,sizeof(s.backing),"%s-db",s.path);
|
||||
if(n<0||(size_t)n>=sizeof(s.backing)||!absent(s.path)||!absent(s.backing))die("Private fixture path already exists or overflows");
|
||||
s.cert_return=import_cert(der,(int32_t)der_length,1,NULL,NULL,1,&s.cert,&s.identity,&s.cert_status);owned(s.cert);owned(s.identity);
|
||||
track(&s,s.cert,"import-cert-track",&s.cert_tracked);
|
||||
if(s.identity)track(&s,s.identity,"unexpected-import-identity-track",&s.identity_tracked);
|
||||
if(s.cert_return!=1||s.cert_status||!s.cert||CFGetTypeID(s.cert)!=SecCertificateGetTypeID()||s.identity||s.failed){s.failed=1;goto cleanup;}
|
||||
s.modern_return=create_key(key,(int32_t)key_length,2,0,&s.modern,&s.error);owned(s.modern);owned(s.error);
|
||||
s.modern_error_present=s.error!=NULL;if(s.error){if(CFGetTypeID(s.error)==CFErrorGetTypeID())s.modern_error=CFErrorGetCode(s.error);else s.failed=1;}DROP(s.error);
|
||||
if(s.modern_return!=1||!s.modern||CFGetTypeID(s.modern)!=SecKeyGetTypeID()||s.modern_error_present||s.failed){s.failed=1;goto cleanup;}
|
||||
s.public_key=copy_public(s.modern);owned(s.public_key);if(!s.public_key||CFGetTypeID(s.public_key)!=SecKeyGetTypeID()){s.failed=1;goto cleanup;}
|
||||
s.create_status=create_chain(s.path,129,password,&s.keychain);owned(s.keychain);wipe(password,sizeof(password));
|
||||
if(s.keychain){created_refs++;s.keychain_identity=s.keychain;s.initial_owner=1;s.registry_active=1;s.logical_owners=1;char actual[PATH_MAX];s.path_status=keychain_path(s.keychain,actual);s.path_verified=private_path(&s,s.keychain);}
|
||||
if(s.create_status||!s.keychain||s.path_status||!s.path_verified){s.failed=1;goto cleanup;}
|
||||
s.lock_status=never_lock(s.keychain);if(s.lock_status){s.failed=1;goto cleanup;}
|
||||
s.external_return=external_key(s.modern,&s.external,&s.error);owned(s.external);owned(s.error);
|
||||
s.external_error_present=s.error!=NULL;if(s.error){if(CFGetTypeID(s.error)==CFErrorGetTypeID())s.external_error=CFErrorGetCode(s.error);else s.failed=1;}DROP(s.error);
|
||||
if(s.external_return!=1||!s.external||CFGetTypeID(s.external)!=CFDataGetTypeID()||s.external_error_present||s.failed||CFDataGetLength(s.external)<=0||CFDataGetLength(s.external)>65536){s.failed=1;goto cleanup;}
|
||||
s.key_return=import_key(CFDataGetBytePtr(s.external),(int32_t)CFDataGetLength(s.external),1,&s.legacy,&s.key_status);owned(s.legacy);
|
||||
DROP(s.external);DROP(s.modern);DROP(s.public_key); // Installed SecKeyPair releases private before public.
|
||||
if(s.key_return!=1||s.key_status||!s.legacy||CFGetTypeID(s.legacy)!=SecKeyGetTypeID()){s.failed=1;goto cleanup;}
|
||||
int associated=0;s.outer=copied_chain(&s,s.cert,"move-outer-copy",&associated);
|
||||
untrack(&s,s.cert,"move-cert-untrack",&s.cert_tracked);
|
||||
if(s.failed)goto cleanup;
|
||||
s.move_return=move_key(s.cert,s.keychain,s.legacy,&s.identity,&s.move_status);owned(s.identity);
|
||||
track(&s,s.cert,"move-cert-track",&s.cert_tracked);track(&s,s.identity,"move-identity-track",&s.identity_tracked);DROP(s.outer);
|
||||
if(s.move_return!=1||s.move_status||!s.identity||CFGetTypeID(s.identity)!=SecIdentityGetTypeID()||s.failed){s.failed=1;goto cleanup;}
|
||||
s.copy_cert_status=copy_cert(s.identity,&s.copied);owned(s.copied);track(&s,s.copied,"identity-cert-track",&s.copied_tracked);
|
||||
if(s.copy_cert_status||!s.copied||CFGetTypeID(s.copied)!=SecCertificateGetTypeID()||s.failed){s.failed=1;goto cleanup;}
|
||||
if(iteration==1||iteration==REPETITIONS){s.leaf_checked=1;s.leaf_matches=leaf_equal(s.copied,der,der_length);
|
||||
if(!s.leaf_matches){s.failed=1;goto cleanup;}}
|
||||
cleanup:
|
||||
wipe(password,sizeof(password));DROP(s.error);DROP(s.external);DROP(s.modern);DROP(s.public_key);DROP(s.outer);
|
||||
untrack(&s,s.cert,"release-original-cert",&s.cert_tracked);DROP(s.cert);
|
||||
if(s.initial_owner){s.initial_owner=0;s.import_state_released=1;s.import_owners_before=s.logical_owners;
|
||||
relinquish(&s,"release-import-state",0);s.import_owners_after=s.logical_owners;}
|
||||
untrack(&s,s.copied,"release-copied-cert",&s.copied_tracked);DROP(s.copied);
|
||||
untrack(&s,s.identity,"release-identity",&s.identity_tracked);DROP(s.identity);
|
||||
DROP(s.legacy); // Explicit lifetime; managed helper does not scope this local with using.
|
||||
if(defer_delete&&s.pending_delete&&!s.failed){
|
||||
// This counts only observed returned CF owners, not bridge-internal references.
|
||||
if(!s.keychain||s.registry_active||s.logical_owners||s.initial_owner||s.cert_tracked||s.copied_tracked||s.identity_tracked||s.cert||s.copied||s.identity||s.legacy||s.modern||s.public_key||s.external||s.error||s.outer||all_created-all_released!=1){s.failed=1;}
|
||||
else delete_owner(&s,"after-all-item-releases",0);
|
||||
}
|
||||
if(s.keychain){s.failed=1;s.fallback_cleanup=1;delete_owner(&s,"failure-fallback-after-items",0);}
|
||||
unsigned made=all_created-before_created,released=all_released-before_released;
|
||||
if(made!=released||s.logical_owners||s.registry_active||s.cert_tracked||s.copied_tracked||s.identity_tracked)s.failed=1;
|
||||
if(!s.failed&&(s.copy_count!=9||!s.import_state_released||!s.zero.stage||!s.deletion.stage||!s.deleted))s.failed=1;
|
||||
fprintf(stdout,"{\"kind\":\"operation\",\"iteration\":%u,\"certReturn\":%d,\"certStatus\":%d,\"modernReturn\":%d,\"modernErrorCode\":%ld,\"modernErrorPresent\":%s,\"createStatus\":%d,\"pathStatus\":%d,\"neverLockStatus\":%d,\"externalReturn\":%d,\"externalErrorCode\":%ld,\"externalErrorPresent\":%s,\"legacyReturn\":%d,\"legacyStatus\":%d,\"moveReturn\":%d,\"moveStatus\":%d,\"copyCertStatus\":%d,\"deleteStatus\":%d,\"privatePathVerified\":%s,\"deleteStage\":\"%s\",\"deleteLiveReferences\":{\"copy\":%s,\"originalCertificate\":%s,\"copiedCertificate\":%s,\"identity\":%s,\"legacyKey\":%s},\"ownedOutputsAtDelete\":%u,\"logicalZeroStage\":\"%s\",\"logicalZeroLiveReferences\":{\"copy\":%s,\"originalCertificate\":%s,\"copiedCertificate\":%s,\"identity\":%s,\"legacyKey\":%s},\"ownedOutputsAtLogicalZero\":%u,\"importStateReleased\":%s,\"importOwnersBefore\":%u,\"importOwnersAfter\":%u,\"leafIdentityChecked\":%s,\"leafIdentityMatches\":%s,\"fallbackCleanup\":%s,\"logicalOwnersRemaining\":%u,\"ownedOutputs\":%u,\"releasedOutputs\":%u,\"failed\":%s,\"copies\":[",iteration,s.cert_return,s.cert_status,s.modern_return,(long)s.modern_error,s.modern_error_present?"true":"false",s.create_status,s.path_status,s.lock_status,s.external_return,(long)s.external_error,s.external_error_present?"true":"false",s.key_return,s.key_status,s.move_return,s.move_status,s.copy_cert_status,s.delete_status,s.path_verified?"true":"false",s.deletion.stage?s.deletion.stage:"not-attempted",s.deletion.copy_live?"true":"false",s.deletion.cert_live?"true":"false",s.deletion.copied_live?"true":"false",s.deletion.identity_live?"true":"false",s.deletion.legacy_live?"true":"false",s.deletion.owned_outputs_remaining,s.zero.stage?s.zero.stage:"not-reached",s.zero.copy_live?"true":"false",s.zero.cert_live?"true":"false",s.zero.copied_live?"true":"false",s.zero.identity_live?"true":"false",s.zero.legacy_live?"true":"false",s.zero.owned_outputs_remaining,s.import_state_released?"true":"false",s.import_owners_before,s.import_owners_after,s.leaf_checked?"true":"false",s.leaf_matches?"true":"false",s.fallback_cleanup?"true":"false",s.logical_owners,made,released,s.failed?"true":"false");
|
||||
for(unsigned i=0;i<s.copy_count;i++){struct copy_result c=s.copies[i];fprintf(stdout,"%s{\"stage\":\"%s\",\"action\":\"%s\",\"status\":%d,\"returnedRef\":%s,\"privateAssociation\":%s,\"logicalOwnersBefore\":%u,\"logicalOwnersAfter\":%u,\"registryOwnerBefore\":%s,\"registryOwnerAfter\":%s,\"nativeOwnerBefore\":%s,\"nativeOwnerAfter\":%s}",i?",":"",c.stage,c.action,c.status,c.present?"true":"false",c.associated?"true":"false",c.owners_before,c.owners_after,c.registry_before?"true":"false",c.registry_after?"true":"false",c.native_owner_before?"true":"false",c.native_owner_after?"true":"false");}
|
||||
fprintf(stdout,"]}\n");fflush(stdout);if(s.failed)die("Native bridge import operation failed after ownership cleanup");
|
||||
}
|
||||
static unsigned char *read_fixture(const char *name,size_t *length){
|
||||
char path[PATH_MAX];int n=snprintf(path,sizeof(path),"%s/%s",seed_root,name);struct stat state;
|
||||
if(n<0||(size_t)n>=sizeof(path))die("Seed fixture path overflow");
|
||||
if(lstat(path,&state)||!S_ISREG(state.st_mode)||(state.st_mode&077)||state.st_nlink!=1||state.st_size<1||state.st_size>65536)die("Expected private bounded regular fixture");
|
||||
FILE *file=fopen(path,"rb");if(!file)die("Fixture read failed");*length=(size_t)state.st_size;
|
||||
unsigned char *bytes=malloc(*length);if(!bytes){fclose(file);die("Fixture allocation failed");}
|
||||
int bad=fread(bytes,1,*length,file)!=*length||ferror(file);fclose(file);if(bad){wipe(bytes,*length);free(bytes);die("Fixture read incomplete");}return bytes;
|
||||
}
|
||||
int main(int argc,char **argv){
|
||||
clock_gettime(CLOCK_MONOTONIC,&started);
|
||||
if(argc!=5||!realpath(argv[1],root)||!realpath(argv[3],seed_root))die("Expected private arm root, pinned bridge and shared seed");
|
||||
arm_order=argv[4];if(strcmp(arm_order,"normal")&&strcmp(arm_order,"deferred"))die("Unknown fixed timing arm");
|
||||
defer_delete=!strcmp(arm_order,"deferred");
|
||||
const char *split=strrchr(root,'/');char expected_seed[PATH_MAX];
|
||||
if(!split||strcmp(split+1,arm_order))die("Expected isolated timing arm root");
|
||||
int n=snprintf(expected_seed,sizeof(expected_seed),"%.*s/seed",(int)(split-root),root);
|
||||
if(n<0||(size_t)n>=sizeof(expected_seed)||strcmp(expected_seed,seed_root))die("Seed is not the shared private sibling");
|
||||
struct stat state;
|
||||
if(stat(root,&state)||!S_ISDIR(state.st_mode)||(state.st_mode&077)||stat(seed_root,&state)||!S_ISDIR(state.st_mode)||(state.st_mode&077))die("Fixture roots must be private0700");
|
||||
load_bridge(argv[2]);size_t der_length,key_length;
|
||||
unsigned char *der=read_fixture("leaf.der",&der_length),*key=read_fixture("private.pkcs1",&key_length);
|
||||
struct fingerprint before=fingerprint("before");checkpoint("before",0);
|
||||
for(unsigned i=1;i<=REPETITIONS;i++){import_operation(i,der,der_length,key,key_length);if(i==1)checkpoint("first",i);}
|
||||
checkpoint("repeated",REPETITIONS);struct timespec idle={5,0};while(nanosleep(&idle,&idle)){if(errno!=EINTR)die("Idle delay failed");}
|
||||
struct fingerprint after=fingerprint("after");image_guard();checkpoint("idle",REPETITIONS);
|
||||
wipe(key,key_length);free(key);free(der);
|
||||
if(strcmp(before.default_sha,after.default_sha)||strcmp(before.search_sha,after.search_sha)||before.search_count!=after.search_count||created_refs!=REPETITIONS||released_refs!=REPETITIONS||all_created!=all_released)die("Fingerprint or ownership guard failed");
|
||||
fprintf(stdout,"{\"kind\":\"complete\",\"order\":\"%s\",\"operations\":200,\"createdRefs\":%u,\"releasedRefs\":%u,\"ownedOutputs\":%u,\"releasedOutputs\":%u,\"readOnlyDefaultAndSearchListUnchanged\":true,\"managedRuntimePresent\":false,\"bridgeSha256\":\"%s\",\"elapsedSeconds\":%.6f,\"fullSoakGate\":false}\n",arm_order,created_refs,released_refs,all_created,all_released,BRIDGE_SHA,elapsed());fflush(stdout);return 0;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{"kind":"fingerprint","stage":"before","defaultStatus":0,"defaultPathStatus":0,"searchStatus":0,"searchPathStatus":0,"defaultSha256":"08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63","searchSha256":"c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c","searchCount":2,"ownedQueryReferencesReleased":2}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"deferred","stage":"before","operations":0,"processId":88965,"utc":"2026-11-10T22:46:59.453Z","elapsedSeconds":0.003065,"rssBytes":7536640,"createdRefs":0,"releasedRefs":0,"managedRuntimePresent":false}
|
||||
{"kind":"operation","iteration":1,"certReturn":1,"certStatus":0,"modernReturn":1,"modernErrorCode":0,"modernErrorPresent":false,"createStatus":0,"pathStatus":0,"neverLockStatus":0,"externalReturn":1,"externalErrorCode":0,"externalErrorPresent":false,"legacyReturn":1,"legacyStatus":0,"moveReturn":1,"moveStatus":0,"copyCertStatus":0,"deleteStatus":0,"privatePathVerified":true,"deleteStage":"after-all-item-releases","deleteLiveReferences":{"copy":false,"originalCertificate":false,"copiedCertificate":false,"identity":false,"legacyKey":false},"ownedOutputsAtDelete":1,"logicalZeroStage":"release-copied-cert","logicalZeroLiveReferences":{"copy":true,"originalCertificate":false,"copiedCertificate":true,"identity":true,"legacyKey":true},"ownedOutputsAtLogicalZero":5,"importStateReleased":true,"importOwnersBefore":2,"importOwnersAfter":1,"leafIdentityChecked":true,"leafIdentityMatches":true,"fallbackCleanup":false,"logicalOwnersRemaining":0,"ownedOutputs":13,"releasedOutputs":13,"failed":false,"copies":[{"stage":"import-cert-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":false,"nativeOwnerAfter":false},{"stage":"move-outer-copy","action":"lookup","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-untrack","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-identity-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":2,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"identity-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":2,"logicalOwnersAfter":3,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-original-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":3,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-copied-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":0,"registryOwnerBefore":true,"registryOwnerAfter":false,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-identity","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":true,"nativeOwnerAfter":true}]}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"deferred","stage":"first","operations":1,"processId":88965,"utc":"2026-11-10T22:47:00.201Z","elapsedSeconds":0.750946,"rssBytes":10878976,"createdRefs":1,"releasedRefs":1,"managedRuntimePresent":false}
|
||||
{"kind":"operation","iteration":200,"certReturn":1,"certStatus":0,"modernReturn":1,"modernErrorCode":0,"modernErrorPresent":false,"createStatus":0,"pathStatus":0,"neverLockStatus":0,"externalReturn":1,"externalErrorCode":0,"externalErrorPresent":false,"legacyReturn":1,"legacyStatus":0,"moveReturn":1,"moveStatus":0,"copyCertStatus":0,"deleteStatus":0,"privatePathVerified":true,"deleteStage":"after-all-item-releases","deleteLiveReferences":{"copy":false,"originalCertificate":false,"copiedCertificate":false,"identity":false,"legacyKey":false},"ownedOutputsAtDelete":1,"logicalZeroStage":"release-copied-cert","logicalZeroLiveReferences":{"copy":true,"originalCertificate":false,"copiedCertificate":true,"identity":true,"legacyKey":true},"ownedOutputsAtLogicalZero":5,"importStateReleased":true,"importOwnersBefore":2,"importOwnersAfter":1,"leafIdentityChecked":true,"leafIdentityMatches":true,"fallbackCleanup":false,"logicalOwnersRemaining":0,"ownedOutputs":13,"releasedOutputs":13,"failed":false,"copies":[{"stage":"import-cert-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":false,"nativeOwnerAfter":false},{"stage":"move-outer-copy","action":"lookup","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-untrack","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-identity-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":2,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"identity-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":2,"logicalOwnersAfter":3,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-original-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":3,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-copied-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":0,"registryOwnerBefore":true,"registryOwnerAfter":false,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-identity","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":true,"nativeOwnerAfter":true}]}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"deferred","stage":"repeated","operations":200,"processId":88965,"utc":"2026-11-10T22:47:10.347Z","elapsedSeconds":10.896725,"rssBytes":14123008,"createdRefs":200,"releasedRefs":200,"managedRuntimePresent":false}
|
||||
{"kind":"fingerprint","stage":"after","defaultStatus":0,"defaultPathStatus":0,"searchStatus":0,"searchPathStatus":0,"defaultSha256":"08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63","searchSha256":"c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c","searchCount":2,"ownedQueryReferencesReleased":4}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"deferred","stage":"idle","operations":200,"processId":88965,"utc":"2026-11-10T22:47:16.069Z","elapsedSeconds":16.618717,"rssBytes":14139392,"createdRefs":200,"releasedRefs":200,"managedRuntimePresent":false}
|
||||
{"kind":"complete","order":"deferred","operations":200,"createdRefs":200,"releasedRefs":200,"ownedOutputs":2402,"releasedOutputs":2402,"readOnlyDefaultAndSearchListUnchanged":true,"managedRuntimePresent":false,"bridgeSha256":"0333994e217a3d111d36d7f31460eea69a286f9fc819e2d7c746df13d2aec46c","elapsedSeconds":17.289693,"fullSoakGate":false}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"remainingOwnedKeychainFilesByArm": {
|
||||
"normal": 0,
|
||||
"deferred": 0
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"allLaunchedChildrenConfirmedReaped": true,
|
||||
"reapOutcomes": [
|
||||
{
|
||||
"processId": 88920,
|
||||
"confirmedReaped": true,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"processId": 88924,
|
||||
"confirmedReaped": true,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"processId": 88928,
|
||||
"confirmedReaped": true,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"processId": 88929,
|
||||
"confirmedReaped": true,
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"processId": 88965,
|
||||
"confirmedReaped": true,
|
||||
"exitCode": 0
|
||||
}
|
||||
],
|
||||
"privateMaterialOverwrittenThenUnlinkedAfterChildReaping": true,
|
||||
"physicalSecureErasureClaimed": false,
|
||||
"status": "passed",
|
||||
"ownedFixtureRootRemoved": true
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c:43:42: warning: 'SecKeychainGetTypeID' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
43 | if(!keychain||CFGetTypeID(keychain)!=SecKeychainGetTypeID())return errSecParam;
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:270:10: note: 'SecKeychainGetTypeID' has been explicitly marked deprecated here
|
||||
270 | CFTypeID SecKeychainGetTypeID(void)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c:45:21: warning: 'SecKeychainGetPath' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
45 | OSStatus status=SecKeychainGetPath(keychain,&length,path);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:474:10: note: 'SecKeychainGetPath' has been explicitly marked deprecated here
|
||||
474 | OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c:56:29: warning: 'SecKeychainCopyDefault' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
56 | OSStatus default_status=SecKeychainCopyDefault(&default_keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:384:10: note: 'SecKeychainCopyDefault' has been explicitly marked deprecated here
|
||||
384 | OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c:60:28: warning: 'SecKeychainCopySearchList' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
60 | OSStatus search_status=SecKeychainCopySearchList(&search);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:404:10: note: 'SecKeychainCopySearchList' has been explicitly marked deprecated here
|
||||
404 | OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c:157:42: warning: 'SecKeychainGetTypeID' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
157 | if(!keychain||CFGetTypeID(keychain)!=SecKeychainGetTypeID())return 0;
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:270:10: note: 'SecKeychainGetTypeID' has been explicitly marked deprecated here
|
||||
270 | CFTypeID SecKeychainGetTypeID(void)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c:187:47: warning: 'SecKeychainGetTypeID' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
187 | int type_ok=!result||CFGetTypeID(result)==SecKeychainGetTypeID();
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:270:10: note: 'SecKeychainGetTypeID' has been explicitly marked deprecated here
|
||||
270 | CFTypeID SecKeychainGetTypeID(void)
|
||||
| ^
|
||||
6 warnings generated.
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{"kind":"fingerprint","stage":"before","defaultStatus":0,"defaultPathStatus":0,"searchStatus":0,"searchPathStatus":0,"defaultSha256":"08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63","searchSha256":"c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c","searchCount":2,"ownedQueryReferencesReleased":2}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"normal","stage":"before","operations":0,"processId":88929,"utc":"2026-11-10T22:46:42.027Z","elapsedSeconds":0.004969,"rssBytes":7667712,"createdRefs":0,"releasedRefs":0,"managedRuntimePresent":false}
|
||||
{"kind":"operation","iteration":1,"certReturn":1,"certStatus":0,"modernReturn":1,"modernErrorCode":0,"modernErrorPresent":false,"createStatus":0,"pathStatus":0,"neverLockStatus":0,"externalReturn":1,"externalErrorCode":0,"externalErrorPresent":false,"legacyReturn":1,"legacyStatus":0,"moveReturn":1,"moveStatus":0,"copyCertStatus":0,"deleteStatus":0,"privatePathVerified":true,"deleteStage":"release-copied-cert","deleteLiveReferences":{"copy":true,"originalCertificate":false,"copiedCertificate":true,"identity":true,"legacyKey":true},"ownedOutputsAtDelete":5,"logicalZeroStage":"release-copied-cert","logicalZeroLiveReferences":{"copy":true,"originalCertificate":false,"copiedCertificate":true,"identity":true,"legacyKey":true},"ownedOutputsAtLogicalZero":5,"importStateReleased":true,"importOwnersBefore":2,"importOwnersAfter":1,"leafIdentityChecked":true,"leafIdentityMatches":true,"fallbackCleanup":false,"logicalOwnersRemaining":0,"ownedOutputs":13,"releasedOutputs":13,"failed":false,"copies":[{"stage":"import-cert-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":false,"nativeOwnerAfter":false},{"stage":"move-outer-copy","action":"lookup","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-untrack","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-identity-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":2,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"identity-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":2,"logicalOwnersAfter":3,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-original-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":3,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-copied-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":0,"registryOwnerBefore":true,"registryOwnerAfter":false,"nativeOwnerBefore":true,"nativeOwnerAfter":false},{"stage":"release-identity","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":false,"nativeOwnerAfter":false}]}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"normal","stage":"first","operations":1,"processId":88929,"utc":"2026-11-10T22:46:42.988Z","elapsedSeconds":0.965802,"rssBytes":10895360,"createdRefs":1,"releasedRefs":1,"managedRuntimePresent":false}
|
||||
{"kind":"operation","iteration":200,"certReturn":1,"certStatus":0,"modernReturn":1,"modernErrorCode":0,"modernErrorPresent":false,"createStatus":0,"pathStatus":0,"neverLockStatus":0,"externalReturn":1,"externalErrorCode":0,"externalErrorPresent":false,"legacyReturn":1,"legacyStatus":0,"moveReturn":1,"moveStatus":0,"copyCertStatus":0,"deleteStatus":0,"privatePathVerified":true,"deleteStage":"release-copied-cert","deleteLiveReferences":{"copy":true,"originalCertificate":false,"copiedCertificate":true,"identity":true,"legacyKey":true},"ownedOutputsAtDelete":5,"logicalZeroStage":"release-copied-cert","logicalZeroLiveReferences":{"copy":true,"originalCertificate":false,"copiedCertificate":true,"identity":true,"legacyKey":true},"ownedOutputsAtLogicalZero":5,"importStateReleased":true,"importOwnersBefore":2,"importOwnersAfter":1,"leafIdentityChecked":true,"leafIdentityMatches":true,"fallbackCleanup":false,"logicalOwnersRemaining":0,"ownedOutputs":13,"releasedOutputs":13,"failed":false,"copies":[{"stage":"import-cert-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":false,"nativeOwnerAfter":false},{"stage":"move-outer-copy","action":"lookup","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-untrack","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":1,"logicalOwnersAfter":1,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"move-identity-track","action":"track","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":2,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"identity-cert-track","action":"track","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":2,"logicalOwnersAfter":3,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-original-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":3,"logicalOwnersAfter":2,"registryOwnerBefore":true,"registryOwnerAfter":true,"nativeOwnerBefore":true,"nativeOwnerAfter":true},{"stage":"release-copied-cert","action":"untrack","status":0,"returnedRef":true,"privateAssociation":true,"logicalOwnersBefore":1,"logicalOwnersAfter":0,"registryOwnerBefore":true,"registryOwnerAfter":false,"nativeOwnerBefore":true,"nativeOwnerAfter":false},{"stage":"release-identity","action":"untrack","status":0,"returnedRef":false,"privateAssociation":false,"logicalOwnersBefore":0,"logicalOwnersAfter":0,"registryOwnerBefore":false,"registryOwnerAfter":false,"nativeOwnerBefore":false,"nativeOwnerAfter":false}]}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"normal","stage":"repeated","operations":200,"processId":88929,"utc":"2026-11-10T22:46:53.036Z","elapsedSeconds":11.013997,"rssBytes":14548992,"createdRefs":200,"releasedRefs":200,"managedRuntimePresent":false}
|
||||
{"kind":"fingerprint","stage":"after","defaultStatus":0,"defaultPathStatus":0,"searchStatus":0,"searchPathStatus":0,"defaultSha256":"08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63","searchSha256":"c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c","searchCount":2,"ownedQueryReferencesReleased":4}
|
||||
{"kind":"checkpoint","mode":"native-bridge-import-timing","order":"normal","stage":"idle","operations":200,"processId":88929,"utc":"2026-11-10T22:46:58.718Z","elapsedSeconds":16.696203,"rssBytes":14581760,"createdRefs":200,"releasedRefs":200,"managedRuntimePresent":false}
|
||||
{"kind":"complete","order":"normal","operations":200,"createdRefs":200,"releasedRefs":200,"ownedOutputs":2402,"releasedOutputs":2402,"readOnlyDefaultAndSearchListUnchanged":true,"managedRuntimePresent":false,"bridgeSha256":"0333994e217a3d111d36d7f31460eea69a286f9fc819e2d7c746df13d2aec46c","elapsedSeconds":17.402910,"fullSoakGate":false}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"immutableBCommit": "ce11a5dcfff19f0d5501674e407b1aa331a083f3",
|
||||
"immutableBSourceSha256": {
|
||||
"NativeImportControl.c": "ed442bacbdbbc3d420864c4b8ddac9bb4a5799d1e1a1e67d33033678e8401648",
|
||||
"native_import.py": "fc4092ab69a9a8b8213697d83c171632248c84c5c4bcbcf59ea6d2faffa82189",
|
||||
"ImportSeed.cs": "feaac1c93bdb0f4e59bd0a9fb213d6de53cb89ece7393356c9d12d318b395c1b",
|
||||
"pure_apple.py": "1b2148f1c20578529355379ab94b439931d7241608a5d5effce8fc86f4af7bc6"
|
||||
},
|
||||
"sourcesSha256": {
|
||||
"NativeImportTimingControl.c": "6c63a71684e4c8823596c00639b242c264f12078baab39522d4c0f554a41f3ea",
|
||||
"native_import_timing.py": "0369c293afdf7db3628992bc71cdc534798927a7ad6e036b8978ecfbee9c57fd"
|
||||
},
|
||||
"nativeBridgeSha256": "0333994e217a3d111d36d7f31460eea69a286f9fc819e2d7c746df13d2aec46c",
|
||||
"managedCryptographySha256": "f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a",
|
||||
"sdkSeedSha256": {
|
||||
"Opc.Ua.Client.dll": "620da406fabdbc75d11f9827ea7e39d2d3c762471bd2264b0d11f1d6cd9247cd",
|
||||
"Opc.Ua.Configuration.dll": "6ed6a594c93c3ff35d1a16539a9fe87c1e2640549cc2f48ed6bae333dc8bf0e7",
|
||||
"Opc.Ua.Core.Schema.dll": "51cfad48657d95d38074bb88be29aea6f5b361a07397247d58838d066b99772e",
|
||||
"Opc.Ua.Core.Types.dll": "a7dd141b8dabe8848ff28c2fb8e16a85a0508e6a49e6b1a1c1e267175b99af96",
|
||||
"Opc.Ua.Core.dll": "9d0857aa6b7f3c49037d4ea557b4da8edf07e146069464481783e66c5c9cd35a",
|
||||
"Opc.Ua.Security.Certificates.dll": "7f4969aceb2f0db5328c6882cb4b117342f3b18905c38acdba600683860c4fd0",
|
||||
"Opc.Ua.Server.dll": "930e714a2f6e15d393840bcdc95e1afa8012bc740c3738a655f958142721864e",
|
||||
"Opc.Ua.Types.dll": "c542f69882f4e8a4ebd5ccc28a3881d6967c7ffb6dcc3c56dc6c776f39c2ede1"
|
||||
},
|
||||
"compileCommand": [
|
||||
"clang",
|
||||
"-std=c11",
|
||||
"-O0",
|
||||
"-g",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/NativeImportTimingControl.c",
|
||||
"-framework",
|
||||
"Security",
|
||||
"-framework",
|
||||
"CoreFoundation",
|
||||
"-o",
|
||||
"/private/tmp/opcua2-native-import-timing-20261110a/NativeImportTimingControl"
|
||||
],
|
||||
"compiler": "Apple clang version 21.0.0 (clang-2100.0.123.102)\nTarget: arm64-apple-darwin25.5.0\nThread model: posix\nInstalledDir: /Library/Developer/CommandLineTools/usr/bin\n",
|
||||
"os": "ProductName:\t\tmacOS\nProductVersion:\t\t26.5.2\nBuildVersion:\t\t25F84\n",
|
||||
"architecture": "arm64",
|
||||
"hostDotnet": ".NET SDK:\n Version: 10.0.403\n Commit: 5a2162bea6\n Workload version: 10.0.400-manifests.a00bebb6\n MSBuild version: 18.9.15+5a2162bea\n\nRuntime Environment:\n OS Name: Mac OS X\n OS Version: 26.5\n OS Platform: Darwin\n RID: osx-arm64\n Base Path: /opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk/10.0.403/\n\n.NET workloads installed:\nThere are no installed workloads to display.\nConfigured to use workload sets when installing new manifests.\nNo workload sets are installed. Run \"dotnet workload restore\" to install a workload set.\n\nHost:\n Version: 10.0.14\n Architecture: arm64\n Commit: 0427b9abbe\n\n.NET SDKs installed:\n 10.0.403 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk]\n\n.NET runtimes installed:\n Microsoft.AspNetCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.AspNetCore.App]\n Microsoft.NETCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App]\n\nOther architectures found:\n None\n\nEnvironment variables:\n Not set\n\nglobal.json file:\n <user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/global.json\n\nLearn more:\n https://aka.ms/dotnet/info\n\nDownload .NET:\n https://aka.ms/dotnet/download\n",
|
||||
"order": [
|
||||
"normal",
|
||||
"deferred"
|
||||
],
|
||||
"repetitionsPerArm": 200,
|
||||
"stages": [
|
||||
"before",
|
||||
"first",
|
||||
"repeated",
|
||||
"idle"
|
||||
],
|
||||
"idleSeconds": 5,
|
||||
"fullSoakGate": false,
|
||||
"managedCallerInMeasuredChildren": false,
|
||||
"sharedSingleFreshPrivateSeed": true,
|
||||
"fixtureCreationUmask": "0077",
|
||||
"onlyTimingChange": "Retire logical ownership at zero in both; defer physical Delete+initial CFRelease until observed item/key/data/copy/error refs are released.",
|
||||
"observedReturnedOwnershipOnly": true,
|
||||
"checkpointDeadlineSecondsPerArm": 180,
|
||||
"binarySha256": "cec035355aea998d6dd9311561b23e1617a1096191847cf99f1a0a90a7b6d112",
|
||||
"seedBinarySha256": "36e648ac37b61cb5dd65f03dcf5db555fc297d23243c42e282ef522f15a8a7a1",
|
||||
"linkedLibraries": "/private/tmp/opcua2-native-import-timing-20261110a/NativeImportTimingControl:\n\t/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 61901.101.4)\n\t/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 4424.1.255)\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1356.0.0)\n"
|
||||
}
|
||||
+356
@@ -0,0 +1,356 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"order": [
|
||||
"normal",
|
||||
"deferred"
|
||||
],
|
||||
"seed": {
|
||||
"kind": "seed",
|
||||
"leafSha256": "811a4e6cd2b5b21cc3e28d174b4a57dacc83d1732809dd11f0de3ed4cae7a9cd",
|
||||
"runtime": "10.0.14",
|
||||
"sdkVersion": "2.0.1.0",
|
||||
"managerDisposed": true,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"keyFormat": "PKCS1-private-RSA",
|
||||
"privateFileMode": "0600",
|
||||
"cryptographyRuntime": {
|
||||
"informationalVersion": "10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa",
|
||||
"sha256": "f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a"
|
||||
}
|
||||
},
|
||||
"sharedSeedIdentityUnchanged": true,
|
||||
"wallSecondsIncludingSeedAndBothArms": 35.54497370799072,
|
||||
"arms": {
|
||||
"normal": {
|
||||
"status": "passed",
|
||||
"order": "normal",
|
||||
"exitCode": 0,
|
||||
"samples": [
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "normal",
|
||||
"stage": "before",
|
||||
"operations": 0,
|
||||
"processId": 88929,
|
||||
"utc": "2026-11-10T22:46:42.027Z",
|
||||
"elapsedSeconds": 0.004969,
|
||||
"rssBytes": 7667712,
|
||||
"createdRefs": 0,
|
||||
"releasedRefs": 0,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 1,
|
||||
"AppleDatabaseShallowBytes": 768,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "normal",
|
||||
"stage": "first",
|
||||
"operations": 1,
|
||||
"processId": 88929,
|
||||
"utc": "2026-11-10T22:46:42.988Z",
|
||||
"elapsedSeconds": 0.965802,
|
||||
"rssBytes": 10895360,
|
||||
"createdRefs": 1,
|
||||
"releasedRefs": 1,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 2,
|
||||
"AppleDatabaseShallowBytes": 1536,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "normal",
|
||||
"stage": "repeated",
|
||||
"operations": 200,
|
||||
"processId": 88929,
|
||||
"utc": "2026-11-10T22:46:53.036Z",
|
||||
"elapsedSeconds": 11.013997,
|
||||
"rssBytes": 14548992,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 201,
|
||||
"AppleDatabaseShallowBytes": 154368,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "normal",
|
||||
"stage": "idle",
|
||||
"operations": 200,
|
||||
"processId": 88929,
|
||||
"utc": "2026-11-10T22:46:58.718Z",
|
||||
"elapsedSeconds": 16.696203,
|
||||
"rssBytes": 14581760,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 201,
|
||||
"AppleDatabaseShallowBytes": 154368,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
}
|
||||
],
|
||||
"complete": {
|
||||
"kind": "complete",
|
||||
"order": "normal",
|
||||
"operations": 200,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"ownedOutputs": 2402,
|
||||
"releasedOutputs": 2402,
|
||||
"readOnlyDefaultAndSearchListUnchanged": true,
|
||||
"managedRuntimePresent": false,
|
||||
"bridgeSha256": "0333994e217a3d111d36d7f31460eea69a286f9fc819e2d7c746df13d2aec46c",
|
||||
"elapsedSeconds": 17.40291,
|
||||
"fullSoakGate": false
|
||||
},
|
||||
"fingerprints": [
|
||||
{
|
||||
"kind": "fingerprint",
|
||||
"stage": "before",
|
||||
"defaultStatus": 0,
|
||||
"defaultPathStatus": 0,
|
||||
"searchStatus": 0,
|
||||
"searchPathStatus": 0,
|
||||
"defaultSha256": "08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63",
|
||||
"searchSha256": "c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c",
|
||||
"searchCount": 2,
|
||||
"ownedQueryReferencesReleased": 2
|
||||
},
|
||||
{
|
||||
"kind": "fingerprint",
|
||||
"stage": "after",
|
||||
"defaultStatus": 0,
|
||||
"defaultPathStatus": 0,
|
||||
"searchStatus": 0,
|
||||
"searchPathStatus": 0,
|
||||
"defaultSha256": "08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63",
|
||||
"searchSha256": "c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c",
|
||||
"searchCount": 2,
|
||||
"ownedQueryReferencesReleased": 4
|
||||
}
|
||||
],
|
||||
"wallSecondsIncludingProbes": 17.802323875017464,
|
||||
"fullSoakGate": false,
|
||||
"logicalZeroStages": {
|
||||
"release-copied-cert": 200
|
||||
},
|
||||
"actualDeletionStages": {
|
||||
"release-copied-cert": 200
|
||||
},
|
||||
"ownedOutputsAtDeleteCounts": {
|
||||
"5": 200
|
||||
},
|
||||
"returnedCopyReferencesByStage": {
|
||||
"import-cert-track": 0,
|
||||
"move-outer-copy": 0,
|
||||
"move-cert-untrack": 0,
|
||||
"move-cert-track": 200,
|
||||
"move-identity-track": 0,
|
||||
"identity-cert-track": 200,
|
||||
"release-original-cert": 200,
|
||||
"release-copied-cert": 200,
|
||||
"release-identity": 0
|
||||
}
|
||||
},
|
||||
"deferred": {
|
||||
"status": "passed",
|
||||
"order": "deferred",
|
||||
"exitCode": 0,
|
||||
"samples": [
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "deferred",
|
||||
"stage": "before",
|
||||
"operations": 0,
|
||||
"processId": 88965,
|
||||
"utc": "2026-11-10T22:46:59.453Z",
|
||||
"elapsedSeconds": 0.003065,
|
||||
"rssBytes": 7536640,
|
||||
"createdRefs": 0,
|
||||
"releasedRefs": 0,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 1,
|
||||
"AppleDatabaseShallowBytes": 768,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "deferred",
|
||||
"stage": "first",
|
||||
"operations": 1,
|
||||
"processId": 88965,
|
||||
"utc": "2026-11-10T22:47:00.201Z",
|
||||
"elapsedSeconds": 0.750946,
|
||||
"rssBytes": 10878976,
|
||||
"createdRefs": 1,
|
||||
"releasedRefs": 1,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 2,
|
||||
"AppleDatabaseShallowBytes": 1536,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "deferred",
|
||||
"stage": "repeated",
|
||||
"operations": 200,
|
||||
"processId": 88965,
|
||||
"utc": "2026-11-10T22:47:10.347Z",
|
||||
"elapsedSeconds": 10.896725,
|
||||
"rssBytes": 14123008,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 201,
|
||||
"AppleDatabaseShallowBytes": 154368,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "native-bridge-import-timing",
|
||||
"order": "deferred",
|
||||
"stage": "idle",
|
||||
"operations": 200,
|
||||
"processId": 88965,
|
||||
"utc": "2026-11-10T22:47:16.069Z",
|
||||
"elapsedSeconds": 16.618717,
|
||||
"rssBytes": 14139392,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 201,
|
||||
"AppleDatabaseShallowBytes": 154368,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
}
|
||||
],
|
||||
"complete": {
|
||||
"kind": "complete",
|
||||
"order": "deferred",
|
||||
"operations": 200,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"ownedOutputs": 2402,
|
||||
"releasedOutputs": 2402,
|
||||
"readOnlyDefaultAndSearchListUnchanged": true,
|
||||
"managedRuntimePresent": false,
|
||||
"bridgeSha256": "0333994e217a3d111d36d7f31460eea69a286f9fc819e2d7c746df13d2aec46c",
|
||||
"elapsedSeconds": 17.289693,
|
||||
"fullSoakGate": false
|
||||
},
|
||||
"fingerprints": [
|
||||
{
|
||||
"kind": "fingerprint",
|
||||
"stage": "before",
|
||||
"defaultStatus": 0,
|
||||
"defaultPathStatus": 0,
|
||||
"searchStatus": 0,
|
||||
"searchPathStatus": 0,
|
||||
"defaultSha256": "08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63",
|
||||
"searchSha256": "c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c",
|
||||
"searchCount": 2,
|
||||
"ownedQueryReferencesReleased": 2
|
||||
},
|
||||
{
|
||||
"kind": "fingerprint",
|
||||
"stage": "after",
|
||||
"defaultStatus": 0,
|
||||
"defaultPathStatus": 0,
|
||||
"searchStatus": 0,
|
||||
"searchPathStatus": 0,
|
||||
"defaultSha256": "08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63",
|
||||
"searchSha256": "c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c",
|
||||
"searchCount": 2,
|
||||
"ownedQueryReferencesReleased": 4
|
||||
}
|
||||
],
|
||||
"wallSecondsIncludingProbes": 17.311765540973283,
|
||||
"fullSoakGate": false,
|
||||
"logicalZeroStages": {
|
||||
"release-copied-cert": 200
|
||||
},
|
||||
"actualDeletionStages": {
|
||||
"after-all-item-releases": 200
|
||||
},
|
||||
"ownedOutputsAtDeleteCounts": {
|
||||
"1": 200
|
||||
},
|
||||
"returnedCopyReferencesByStage": {
|
||||
"import-cert-track": 0,
|
||||
"move-outer-copy": 0,
|
||||
"move-cert-untrack": 0,
|
||||
"move-cert-track": 200,
|
||||
"move-identity-track": 0,
|
||||
"identity-cert-track": 200,
|
||||
"release-original-cert": 200,
|
||||
"release-copied-cert": 200,
|
||||
"release-identity": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"AppleDatabaseCounts": {
|
||||
"normal": [
|
||||
1,
|
||||
2,
|
||||
201,
|
||||
201
|
||||
],
|
||||
"deferred": [
|
||||
1,
|
||||
2,
|
||||
201,
|
||||
201
|
||||
]
|
||||
},
|
||||
"normalReproducedOnePerOperation": true,
|
||||
"fullSoakGate": false,
|
||||
"nativeInventoryIsNotOpenHandlesOrExclusiveRss": true
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
Determining projects to restore...
|
||||
Restored /private/tmp/opcua2-native-import-timing-20261110a/ImportSeed.csproj (in 27 ms).
|
||||
ImportSeed -> /private/tmp/opcua2-native-import-timing-20261110a/bin/Release/net10.0/ImportSeed.dll
|
||||
|
||||
Build succeeded.
|
||||
0 Warning(s)
|
||||
0 Error(s)
|
||||
|
||||
Time Elapsed 00:00:01.12
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"kind":"seed","leafSha256":"811a4e6cd2b5b21cc3e28d174b4a57dacc83d1732809dd11f0de3ed4cae7a9cd","runtime":"10.0.14","sdkVersion":"2.0.1.0","managerDisposed":true,"certificateCoresOutstanding":0,"keyFormat":"PKCS1-private-RSA","privateFileMode":"0600","cryptographyRuntime":{"informationalVersion":"10.0.14\u002B0427b9abbead3fa64c6655eb4290c537397131fa","sha256":"f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a"}}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"status": "completed-fixed-200-per-arm-same-native-inventory",
|
||||
"projection": "Replace local user-home prefix only; selected samples are exact raw row subsets. Raw receipts unchanged.",
|
||||
"rawOutput": "/tmp/opcua2-native-import-timing-20261110a",
|
||||
"rawSha256": {
|
||||
"result.json": "f0b4195fe445259934b91e9c6743437c8427844b8fe5e3a9aafe28847f495986",
|
||||
"provenance.json": "debbe166166bed405fe7099890008ab031f88af88ec827ed81fd951bdacda88a",
|
||||
"native-build.log": "0cc80245a334560a493c68ccce8cde34fddb976c71f9e76b28527143fe6908d5",
|
||||
"seed-build.log": "cca7c5c582a3a468bda2f2ce8450e4cccfdbe714b6c17d3f003697e6221322ba",
|
||||
"seed.jsonl": "9bd84d838438da83590b91b9295c80ea4b001c40900854fe818dfa4511adf46d",
|
||||
"fixture-cleanup.json": "a67553b8bc66b05f3d798a001b0b727b073cd153316dfe6bf086e658a8f5df03",
|
||||
"fixture-before-harness-cleanup.json": "ec5b52f033e4b312e1cb8a046521379b49988093f8f9e5ae33d3b9228e1023ad",
|
||||
"normal/samples.jsonl": "73288755c768065ad0a8b2dad6964696d707f1c6be5a6b8bd531902cb3b4bf51",
|
||||
"deferred/samples.jsonl": "61691ff4c500d2696f6998cd225d19677a0cb8eb47ed8f7545b01f76e4acc456"
|
||||
},
|
||||
"selectedProjectionSha256": {
|
||||
"result.json": "f0b4195fe445259934b91e9c6743437c8427844b8fe5e3a9aafe28847f495986",
|
||||
"provenance.json": "a84e4c30da22fa20b5b9ad260f2e8fe589043b1cc11a9b6399f6b379a1341feb",
|
||||
"native-build.log": "5de56e2de9449ccb8eb65627c9d63ea10ec4f688fbb777afed199b069bdfe223",
|
||||
"seed-build.log": "cca7c5c582a3a468bda2f2ce8450e4cccfdbe714b6c17d3f003697e6221322ba",
|
||||
"seed.jsonl": "9bd84d838438da83590b91b9295c80ea4b001c40900854fe818dfa4511adf46d",
|
||||
"fixture-cleanup.json": "a67553b8bc66b05f3d798a001b0b727b073cd153316dfe6bf086e658a8f5df03",
|
||||
"fixture-before-harness-cleanup.json": "ec5b52f033e4b312e1cb8a046521379b49988093f8f9e5ae33d3b9228e1023ad",
|
||||
"normal-selected-samples.jsonl": "37e19d06a75dc9b8dc9057bd57180a4365a9863b82d36a33c5f308e602faa8cf",
|
||||
"deferred-selected-samples.jsonl": "5072b01bafd497cfa684413290196ae7eb9a005dcd2f8126b14996f853cc52f6"
|
||||
},
|
||||
"selectedSampleRawOneBasedLineNumbers": {
|
||||
"normal": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
203,
|
||||
204,
|
||||
205,
|
||||
206,
|
||||
207
|
||||
],
|
||||
"deferred": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
203,
|
||||
204,
|
||||
205,
|
||||
206,
|
||||
207
|
||||
]
|
||||
},
|
||||
"rawLocalOnlySha256": {
|
||||
"normal/result.json": "73d18077c2ce03a46a693725740c5b7920597c8a2688f5247544c86e19a4024e",
|
||||
"normal/heap-before.txt": "1fe9a6d101d30e43bf40028527cb3db27aa39cd0c363465284e3725c4a51536e",
|
||||
"normal/lsof-before.txt": "184473dff4da97a200fc7bfbddd1174a7c71225ec9fd8cd7eeccad1eeac20879",
|
||||
"normal/heap-first.txt": "99c54edaa70e60bcb22715a7b69e1ba1b0e97ce1782423a3cd93d72c50c98f47",
|
||||
"normal/lsof-first.txt": "31ae587eb32a5eea21e5a6d0d85112006c0d8191ae9f45715546cd4c28683def",
|
||||
"normal/heap-repeated.txt": "51c8430558863e5fc49805ce5355e07288ab86d3ca5272d400649b3ef6cad83c",
|
||||
"normal/lsof-repeated.txt": "31ae587eb32a5eea21e5a6d0d85112006c0d8191ae9f45715546cd4c28683def",
|
||||
"normal/heap-idle.txt": "7b320f3a6dbb3dfdadd7de05508cb917472e9cb8379e2077011f1a13823c2f39",
|
||||
"normal/lsof-idle.txt": "31ae587eb32a5eea21e5a6d0d85112006c0d8191ae9f45715546cd4c28683def",
|
||||
"deferred/result.json": "a27a976e772458b1379172601ade808851723df1069cf4a2ded20f233d24bac5",
|
||||
"deferred/heap-before.txt": "1416ffdfbfc47e6bf4719002b282fa5e57f03e2734d709c6d9f0b40b9141e987",
|
||||
"deferred/lsof-before.txt": "baf3f74ab37a5778e259a92afb4099b24c437063b050d8ddd7a5dae7595651d5",
|
||||
"deferred/heap-first.txt": "8a876d3594b33c6899a77f47432da3e58ca5a3f2c7e889673732ad9473ac345d",
|
||||
"deferred/lsof-first.txt": "a731cbc84c777184be3c2e85d74c91d5e57ef9bd317b8e8a4b52a02a9d754921",
|
||||
"deferred/heap-repeated.txt": "700ae3d358ae3d197ae735cc8250900ddd1a751942930ede5f8d1842b5b9ba73",
|
||||
"deferred/lsof-repeated.txt": "a731cbc84c777184be3c2e85d74c91d5e57ef9bd317b8e8a4b52a02a9d754921",
|
||||
"deferred/heap-idle.txt": "6e40883a16edb59d27904daaf261e10b760ac23cf9d13f895302de7afcd50444",
|
||||
"deferred/lsof-idle.txt": "a731cbc84c777184be3c2e85d74c91d5e57ef9bd317b8e8a4b52a02a9d754921"
|
||||
},
|
||||
"baselineBCommit": "ce11a5dcfff19f0d5501674e407b1aa331a083f3",
|
||||
"noRetainingOwnerDefectMitigationOrFullSoakInference": true
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
#!/usr/bin/env python3
|
||||
"""One matched fixed-200/200 native keychain deletion timing diagnostic."""
|
||||
import argparse
|
||||
from collections import Counter
|
||||
import os
|
||||
from pathlib import Path
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
from native_import import (BRIDGE, BRIDGE_SHA, CHILDREN, COPY_STAGES, CRYPTO_SHA, DOTNET, EXPECTED_SDK, HERE,
|
||||
REAP_OUTCOMES, RUNTIME, STAGES, bounded, complete_rows, reap, save, sha, snapshot,
|
||||
validate_operation, wipe_owned)
|
||||
|
||||
ORDERS = ['normal', 'deferred']
|
||||
IMMUTABLE_B = {
|
||||
'NativeImportControl.c': 'ed442bacbdbbc3d420864c4b8ddac9bb4a5799d1e1a1e67d33033678e8401648',
|
||||
'native_import.py': 'fc4092ab69a9a8b8213697d83c171632248c84c5c4bcbcf59ea6d2faffa82189',
|
||||
'ImportSeed.cs': 'feaac1c93bdb0f4e59bd0a9fb213d6de53cb89ece7393356c9d12d318b395c1b',
|
||||
'pure_apple.py': '1b2148f1c20578529355379ab94b439931d7241608a5d5effce8fc86f4af7bc6',
|
||||
}
|
||||
|
||||
|
||||
def validate_timing(row, order):
|
||||
# B's validator replays logical registry ownership. Physical ownership is checked separately here.
|
||||
projected = {**row, 'deleteStage': row['logicalZeroStage'], 'deleteLiveReferences': row['logicalZeroLiveReferences'],
|
||||
'copies': [{**copy, 'nativeOwnerBefore': copy['registryOwnerBefore'],
|
||||
'nativeOwnerAfter': copy['registryOwnerAfter']} for copy in row['copies']]}
|
||||
validate_operation(projected)
|
||||
if row['ownedOutputsAtLogicalZero'] != 1 + sum(row['logicalZeroLiveReferences'].values()):
|
||||
raise RuntimeError('Observed native CF ownership did not reconcile at logical zero')
|
||||
for index, copy in enumerate(row['copies']):
|
||||
for point in ['Before', 'After']:
|
||||
expected = copy['registryOwner' + point] if order == 'normal' else index > 0
|
||||
if copy['nativeOwner' + point] != expected:
|
||||
raise RuntimeError('Physical keychain owner lifetime did not match selected timing')
|
||||
if order == 'normal':
|
||||
if (row['deleteStage'], row['deleteLiveReferences'], row['ownedOutputsAtDelete']) != (
|
||||
row['logicalZeroStage'], row['logicalZeroLiveReferences'], row['ownedOutputsAtLogicalZero']):
|
||||
raise RuntimeError('Normal delete did not occur at logical zero')
|
||||
elif row['deleteStage'] != 'after-all-item-releases' or any(row['deleteLiveReferences'].values()) or row['ownedOutputsAtDelete'] != 1:
|
||||
raise RuntimeError('Deferred delete did not hold exactly its one observed native owner')
|
||||
|
||||
|
||||
def seed_stamp(root):
|
||||
values = []
|
||||
for name in ['leaf.der', 'private.pkcs1']:
|
||||
info = (root / name).lstat()
|
||||
if not stat.S_ISREG(info.st_mode) or stat.S_IMODE(info.st_mode) != 0o600 or info.st_nlink != 1:
|
||||
raise RuntimeError('Shared seed inputs must be private0600 regular files')
|
||||
values.append((info.st_dev, info.st_ino, info.st_size, info.st_mtime_ns))
|
||||
return values # Check same files privately; no private-key bytes, hashes or inode IDs in receipts.
|
||||
|
||||
|
||||
def fingerprint_key(row):
|
||||
if any(row[k] for k in ['defaultStatus', 'defaultPathStatus', 'searchStatus', 'searchPathStatus']):
|
||||
raise RuntimeError('Keychain fingerprint query failed')
|
||||
return row['defaultSha256'], row['searchSha256'], row['searchCount']
|
||||
|
||||
|
||||
def arm(binary, seed, task, output, order):
|
||||
task.mkdir(mode=0o700); (task / 'tmp').mkdir(mode=0o700); output.mkdir(mode=0o700)
|
||||
started = time.monotonic()
|
||||
with (output / 'samples.jsonl').open('w') as log:
|
||||
process = subprocess.Popen([str(binary), str(task), str(BRIDGE), str(seed), order], stdout=log, stderr=subprocess.STDOUT,
|
||||
env=dict(os.environ, TMPDIR=str(task / 'tmp')), start_new_session=True)
|
||||
CHILDREN.append(process)
|
||||
try:
|
||||
deadline = time.monotonic() + 180
|
||||
samples = []
|
||||
for stage in STAGES:
|
||||
while True:
|
||||
rows = complete_rows(output / 'samples.jsonl')
|
||||
if any(r['kind'] == 'failed' for r in rows):
|
||||
raise RuntimeError(order + ' timing child failed; preserve raw statuses')
|
||||
matching = [r for r in rows if r['kind'] == 'checkpoint' and r['stage'] == stage]
|
||||
if matching:
|
||||
samples.append({**matching[0], **snapshot(process.pid, task, output, stage)})
|
||||
(task / ('continue-' + stage)).touch()
|
||||
break
|
||||
if process.poll() is not None or time.monotonic() >= deadline:
|
||||
raise RuntimeError(order + ' checkpoint exceeded bound: ' + stage)
|
||||
time.sleep(.05)
|
||||
status = process.wait(timeout=15)
|
||||
rows = complete_rows(output / 'samples.jsonl')
|
||||
operations = [r for r in rows if r['kind'] == 'operation']
|
||||
fingerprints = [r for r in rows if r['kind'] == 'fingerprint']
|
||||
complete = [r for r in rows if r['kind'] == 'complete']
|
||||
checkpoints = [r for r in rows if r['kind'] == 'checkpoint']
|
||||
if (status or len(rows) != 207 or len(complete) != 1 or [r['iteration'] for r in operations] != list(range(1, 201))
|
||||
or [r['stage'] for r in fingerprints] != ['before', 'after'] or [r['stage'] for r in checkpoints] != STAGES
|
||||
or [r['operations'] for r in checkpoints] != [0, 1, 200, 200] or any(r['order'] != order or r['managedRuntimePresent'] for r in checkpoints)):
|
||||
raise RuntimeError(order + ' fixed operation/checkpoint counts failed')
|
||||
for row in operations:
|
||||
validate_timing(row, order)
|
||||
done = complete[0]
|
||||
if (done['order'] != order or done['operations'] != 200 or done['createdRefs'] != 200 or done['releasedRefs'] != 200
|
||||
or done['bridgeSha256'] != BRIDGE_SHA or done['managedRuntimePresent'] or not done['readOnlyDefaultAndSearchListUnchanged']
|
||||
or done['ownedOutputs'] != sum(r['ownedOutputs'] for r in operations) or done['releasedOutputs'] != sum(r['releasedOutputs'] for r in operations)
|
||||
or fingerprint_key(fingerprints[0]) != fingerprint_key(fingerprints[1])):
|
||||
raise RuntimeError(order + ' completion/ownership/fingerprint guard failed')
|
||||
if any(samples[-1][k] for k in ['ownedKeychainFdCount', 'ownedKeychainFileCount']):
|
||||
raise RuntimeError(order + ' private keychain files/descriptors retained')
|
||||
result = {'status': 'passed', 'order': order, 'exitCode': status, 'samples': samples, 'complete': done,
|
||||
'fingerprints': fingerprints, 'wallSecondsIncludingProbes': time.monotonic() - started, 'fullSoakGate': False,
|
||||
'logicalZeroStages': dict(Counter(r['logicalZeroStage'] for r in operations)),
|
||||
'actualDeletionStages': dict(Counter(r['deleteStage'] for r in operations)),
|
||||
'ownedOutputsAtDeleteCounts': dict(Counter(r['ownedOutputsAtDelete'] for r in operations)),
|
||||
'returnedCopyReferencesByStage': {stage: sum(c['returnedRef'] for r in operations for c in r['copies'] if c['stage'] == stage) for stage in COPY_STAGES}}
|
||||
save(output / 'result.json', result)
|
||||
return result
|
||||
finally:
|
||||
reap(process)
|
||||
|
||||
|
||||
def main():
|
||||
os.umask(0o077)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--references', required=True, type=Path)
|
||||
parser.add_argument('--output', required=True, type=Path, help='Fresh private paired output')
|
||||
args = parser.parse_args()
|
||||
if sys.platform != 'darwin' or os.uname().machine != 'arm64':
|
||||
parser.error('Pinned diagnostic requires macOS arm64')
|
||||
if {name: sha(HERE / name) for name in IMMUTABLE_B} != IMMUTABLE_B:
|
||||
raise RuntimeError('Immutable B sources changed')
|
||||
if sha(BRIDGE) != BRIDGE_SHA or sha(RUNTIME / 'System.Security.Cryptography.dll') != CRYPTO_SHA:
|
||||
raise RuntimeError('Installed native/managed cryptography identity changed')
|
||||
references = args.references.resolve()
|
||||
if {p.name: sha(p) for p in references.glob('Opc.Ua*.dll')} != EXPECTED_SDK:
|
||||
raise RuntimeError('Pinned SDK2 seed binary set changed')
|
||||
output = args.output.resolve(); output.mkdir(parents=True, exist_ok=False)
|
||||
binary = output / 'NativeImportTimingControl'
|
||||
command = ['clang', '-std=c11', '-O0', '-g', '-Wall', '-Wextra', str(HERE / 'NativeImportTimingControl.c'),
|
||||
'-framework', 'Security', '-framework', 'CoreFoundation', '-o', str(binary)]
|
||||
provenance = {'immutableBCommit': 'ce11a5dcfff19f0d5501674e407b1aa331a083f3', 'immutableBSourceSha256': IMMUTABLE_B,
|
||||
'sourcesSha256': {name: sha(HERE / name) for name in ['NativeImportTimingControl.c', 'native_import_timing.py']},
|
||||
'nativeBridgeSha256': BRIDGE_SHA, 'managedCryptographySha256': CRYPTO_SHA, 'sdkSeedSha256': EXPECTED_SDK,
|
||||
'compileCommand': command, 'compiler': subprocess.check_output(['clang', '--version'], text=True, timeout=10),
|
||||
'os': subprocess.check_output(['sw_vers'], text=True, timeout=10), 'architecture': os.uname().machine,
|
||||
'hostDotnet': subprocess.check_output([DOTNET, '--info'], text=True, timeout=10),
|
||||
'order': ORDERS, 'repetitionsPerArm': 200, 'stages': STAGES, 'idleSeconds': 5, 'fullSoakGate': False,
|
||||
'managedCallerInMeasuredChildren': False, 'sharedSingleFreshPrivateSeed': True, 'fixtureCreationUmask': '0077',
|
||||
'onlyTimingChange': 'Retire logical ownership at zero in both; defer physical Delete+initial CFRelease until observed item/key/data/copy/error refs are released.',
|
||||
'observedReturnedOwnershipOnly': True, 'checkpointDeadlineSecondsPerArm': 180}
|
||||
save(output / 'provenance.json', provenance)
|
||||
bounded(command, output / 'native-build.log', 60)
|
||||
project = ET.Element('Project', Sdk='Microsoft.NET.Sdk'); properties = ET.SubElement(project, 'PropertyGroup')
|
||||
for name, value in {'OutputType': 'Exe', 'TargetFramework': 'net10.0', 'ImplicitUsings': 'enable', 'Nullable': 'enable',
|
||||
'EnableDefaultCompileItems': 'false', 'TreatWarningsAsErrors': 'true', 'UseSharedCompilation': 'false'}.items():
|
||||
ET.SubElement(properties, name).text = value
|
||||
items = ET.SubElement(project, 'ItemGroup'); ET.SubElement(items, 'FrameworkReference', Include='Microsoft.AspNetCore.App')
|
||||
ET.SubElement(items, 'Compile', Include=str(HERE / 'ImportSeed.cs'))
|
||||
for name in EXPECTED_SDK:
|
||||
ref = ET.SubElement(items, 'Reference', Include=Path(name).stem); ET.SubElement(ref, 'HintPath').text = str(references / name)
|
||||
ET.indent(project); ET.ElementTree(project).write(output / 'ImportSeed.csproj', encoding='unicode')
|
||||
bounded([DOTNET, 'build', str(output / 'ImportSeed.csproj'), '-c', 'Release', '-m:1', '--disable-build-servers', '--nologo'], output / 'seed-build.log', 120)
|
||||
provenance['binarySha256'] = sha(binary)
|
||||
provenance['seedBinarySha256'] = sha(output / 'bin/Release/net10.0/ImportSeed.dll')
|
||||
provenance['linkedLibraries'] = subprocess.check_output(['otool', '-L', str(binary)], text=True, timeout=10)
|
||||
save(output / 'provenance.json', provenance)
|
||||
task = output / 'task'; task.mkdir(mode=0o700); seed = task / 'seed'
|
||||
for name in ['seed', 'seed-tmp', 'seed-data']:
|
||||
(task / name).mkdir(mode=0o700)
|
||||
started = time.monotonic()
|
||||
try:
|
||||
bounded([DOTNET, str(output / 'bin/Release/net10.0/ImportSeed.dll'), str(seed)], output / 'seed.jsonl', 75,
|
||||
env=dict(os.environ, TMPDIR=str(task / 'seed-tmp'), XDG_DATA_HOME=str(task / 'seed-data')))
|
||||
rows = complete_rows(output / 'seed.jsonl')
|
||||
if len(rows) != 1 or rows[0]['kind'] != 'seed' or rows[0]['sdkVersion'] != '2.0.1.0' or rows[0]['cryptographyRuntime']['sha256'] != CRYPTO_SHA:
|
||||
raise RuntimeError('Seed/runtime count or identity mismatch')
|
||||
seed_row = rows[0]
|
||||
if any(p.stat().st_mode & 0o077 for p in seed.rglob('*') if p.is_file()):
|
||||
raise RuntimeError('Seed file permissions are not private')
|
||||
wipe_owned(seed / 'pki'); wipe_owned(task / 'seed-tmp'); wipe_owned(task / 'seed-data')
|
||||
same_seed = seed_stamp(seed)
|
||||
results = {}
|
||||
for order in ORDERS:
|
||||
if seed_stamp(seed) != same_seed or sha(seed / 'leaf.der') != seed_row['leafSha256'] or sha(BRIDGE) != BRIDGE_SHA or sha(binary) != provenance['binarySha256']:
|
||||
raise RuntimeError('Shared seed or pinned measured binary changed')
|
||||
results[order] = arm(binary, seed, task / order, output / order, order)
|
||||
if seed_stamp(seed) != same_seed or sha(seed / 'leaf.der') != seed_row['leafSha256']:
|
||||
raise RuntimeError('Shared private seed changed across measured arms')
|
||||
if len({fingerprint_key(row) for result in results.values() for row in result['fingerprints']}) != 1:
|
||||
raise RuntimeError('Read-only keychain fingerprints differ across paired arms')
|
||||
counts = {order: [r['AppleDatabaseCount'] for r in results[order]['samples']] for order in ORDERS}
|
||||
normal = counts['normal']
|
||||
save(output / 'result.json', {'status': 'passed', 'order': ORDERS, 'seed': seed_row, 'sharedSeedIdentityUnchanged': True,
|
||||
'wallSecondsIncludingSeedAndBothArms': time.monotonic() - started, 'arms': results, 'AppleDatabaseCounts': counts,
|
||||
'normalReproducedOnePerOperation': normal[1] == normal[0] + 1 and normal[2] == normal[3] == normal[0] + 200,
|
||||
'fullSoakGate': False, 'nativeInventoryIsNotOpenHandlesOrExclusiveRss': True})
|
||||
finally:
|
||||
save(output / 'fixture-before-harness-cleanup.json', {'remainingOwnedKeychainFilesByArm': {
|
||||
order: sum(p.is_file() and '.keychain' in p.name for p in (task / order / 'tmp').rglob('*')) for order in ORDERS}})
|
||||
all_reaped = all(child.returncode is not None for child in CHILDREN)
|
||||
cleanup = {'allLaunchedChildrenConfirmedReaped': all_reaped, 'reapOutcomes': REAP_OUTCOMES,
|
||||
'privateMaterialOverwrittenThenUnlinkedAfterChildReaping': False, 'physicalSecureErasureClaimed': False}
|
||||
if not all_reaped:
|
||||
cleanup.update(status='failed-preserved-private-fixture', ownedFixtureRootRemoved=False)
|
||||
save(output / 'fixture-cleanup.json', cleanup)
|
||||
raise RuntimeError('A launched child was not reaped; private fixture preserved')
|
||||
try:
|
||||
wipe_owned(task)
|
||||
cleanup.update(status='passed', ownedFixtureRootRemoved=not task.exists(),
|
||||
privateMaterialOverwrittenThenUnlinkedAfterChildReaping=True)
|
||||
except Exception as error:
|
||||
cleanup.update(status='failed', errorType=type(error).__name__, ownedFixtureRootRemoved=not task.exists())
|
||||
raise
|
||||
finally:
|
||||
save(output / 'fixture-cleanup.json', cleanup)
|
||||
print(output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user