@ctrl-spc/cs 0.7.13 → 0.7.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -3
- package/dist/autostart.js +103 -122
- package/dist/companion-ui.js +34 -6
- package/dist/companion.js +59 -150
- package/dist/config.js +52 -1
- package/dist/daemon-lifecycle.js +548 -0
- package/dist/daemon-lock.js +149 -42
- package/dist/daemon-processes.js +756 -0
- package/dist/daemon.js +14 -46
- package/dist/darwin-coalition.js +340 -0
- package/dist/index.js +70 -74
- package/dist/login.js +5 -3
- package/dist/native/darwin-coalition +0 -0
- package/dist/native/darwin-coalition.build.json +1 -0
- package/dist/native/darwin-coalition.c +145 -0
- package/dist/orchestrator.js +620 -428
- package/dist/panel3/checkout.js +100 -8
- package/dist/panel3/prompt.js +16 -8
- package/dist/panel3/run.js +891 -541
- package/dist/panel3/spawn.js +59 -11
- package/dist/panel3/tools.js +28 -5
- package/dist/presence.js +183 -24
- package/dist/supabase.js +43 -9
- package/dist/win-shell.js +464 -1
- package/dist/windows-job.js +312 -0
- package/package.json +4 -3
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/* The launchd job is the execution owner; this helper only reads and signals
|
|
2
|
+
* its kernel resource coalition. No privilege or runtime compiler is required.
|
|
3
|
+
* Apple exports these SPI but omits their structures from the public SDK.
|
|
4
|
+
* Check every ABI size/capability, and fail closed when unavailable.
|
|
5
|
+
* Sources: apple-oss-distributions/xnu: bsd/sys/proc_info_private.h,
|
|
6
|
+
* osfmk/mach/coalition.h, osfmk/kern/coalition.c, bsd/kern/sys_coalition.c.
|
|
7
|
+
*/
|
|
8
|
+
#include <libproc.h>
|
|
9
|
+
#include <sys/sysctl.h>
|
|
10
|
+
#include <dlfcn.h>
|
|
11
|
+
#include <errno.h>
|
|
12
|
+
#include <inttypes.h>
|
|
13
|
+
#include <signal.h>
|
|
14
|
+
#include <stdio.h>
|
|
15
|
+
#include <stdlib.h>
|
|
16
|
+
#include <string.h>
|
|
17
|
+
#include <time.h>
|
|
18
|
+
#include <unistd.h>
|
|
19
|
+
|
|
20
|
+
struct coalition_info { uint64_t ids[2], reserved[3]; };
|
|
21
|
+
struct unique_info { uint8_t uuid[16]; uint64_t unique, parent; int32_t version, parent_version; uint64_t reserved[2]; };
|
|
22
|
+
struct process_info { struct proc_bsdinfo bsd; struct unique_info unique; };
|
|
23
|
+
_Static_assert(sizeof(struct coalition_info) == 40, "coalition ABI");
|
|
24
|
+
_Static_assert(sizeof(struct unique_info) == 56, "process ABI");
|
|
25
|
+
static int (*resource_usage)(uint64_t, void *, size_t);
|
|
26
|
+
static int (*signal_token)(audit_token_t *, int);
|
|
27
|
+
static char boot[64];
|
|
28
|
+
|
|
29
|
+
static void fail(const char *message) { fprintf(stderr, "%s (OS error %d).\n", message, errno); exit(1); }
|
|
30
|
+
static void changed(void) { fputs("Mac execution membership changed during inspection.\n",stderr); exit(75); }
|
|
31
|
+
static uint64_t number(const char *text) {
|
|
32
|
+
char *end; errno=0; uint64_t value=strtoull(text,&end,10);
|
|
33
|
+
if(errno || !*text || *end || !value) fail("Invalid Mac execution identity");
|
|
34
|
+
return value;
|
|
35
|
+
}
|
|
36
|
+
static int coalition(pid_t pid, uint64_t *id) {
|
|
37
|
+
struct coalition_info info={0}; int n=proc_pidinfo(pid,20,0,&info,sizeof(info));
|
|
38
|
+
if(n==sizeof(info)) { *id=info.ids[0]; return 1; }
|
|
39
|
+
if(n==0 && (errno==ESRCH || errno==ENOENT)) return 0;
|
|
40
|
+
fail("Mac execution ownership cannot be inspected"); return 0;
|
|
41
|
+
}
|
|
42
|
+
static int process_info(pid_t pid, struct process_info *info) {
|
|
43
|
+
int n=proc_pidinfo(pid,18,0,info,sizeof(*info));
|
|
44
|
+
if(n==sizeof(*info)) return 1;
|
|
45
|
+
if(n==0 && (errno==ESRCH || errno==ENOENT)) return 0;
|
|
46
|
+
fail("Mac process lifetime cannot be inspected"); return 0;
|
|
47
|
+
}
|
|
48
|
+
static int active(uint64_t id, uint64_t *count) {
|
|
49
|
+
uint64_t usage[2]={0};
|
|
50
|
+
if(resource_usage(id,usage,sizeof(usage))!=0) {
|
|
51
|
+
if(errno==ESRCH) { *count=0; return 0; }
|
|
52
|
+
fail("Mac execution membership cannot be inspected");
|
|
53
|
+
}
|
|
54
|
+
if(usage[1]>usage[0]) fail("Invalid Mac execution membership");
|
|
55
|
+
*count=usage[0]-usage[1]; return 1;
|
|
56
|
+
}
|
|
57
|
+
static void capability(void) {
|
|
58
|
+
resource_usage=dlsym(RTLD_DEFAULT,"coalition_info_resource_usage");
|
|
59
|
+
signal_token=dlsym(RTLD_DEFAULT,"proc_signal_with_audittoken");
|
|
60
|
+
size_t size=sizeof(boot);
|
|
61
|
+
if(!resource_usage || !signal_token || sysctlbyname("kern.bootsessionuuid",boot,&size,NULL,0)!=0 || size<36 || size>sizeof(boot))
|
|
62
|
+
fail("This Mac cannot verify safe agent execution; no agent was started");
|
|
63
|
+
uint64_t id, count; struct process_info info={0};
|
|
64
|
+
if(!coalition(getpid(),&id) || !process_info(getpid(),&info) || !active(id,&count))
|
|
65
|
+
fail("This Mac cannot verify safe agent execution; no agent was started");
|
|
66
|
+
}
|
|
67
|
+
static void same_boot(const char *expected) {
|
|
68
|
+
if(strcmp(expected,boot)) fail("Mac execution belongs to a different boot");
|
|
69
|
+
}
|
|
70
|
+
static void birth(struct process_info *info, char *output, size_t capacity) {
|
|
71
|
+
time_t seconds=(time_t)info->bsd.pbi_start_tvsec; struct tm tm; char date[32];
|
|
72
|
+
gmtime_r(&seconds,&tm); strftime(date,sizeof(date),"%Y-%m-%dT%H:%M:%S",&tm);
|
|
73
|
+
snprintf(output,capacity,"%s.%06"PRIu64"Z",date,info->bsd.pbi_start_tvusec);
|
|
74
|
+
}
|
|
75
|
+
int main(int argc,char **argv) {
|
|
76
|
+
capability();
|
|
77
|
+
if(argc==5 && !strcmp(argv[1],"signal-process")) {
|
|
78
|
+
same_boot(argv[2]); pid_t pid=(pid_t)number(argv[3]); struct process_info info={0}; char started[64];
|
|
79
|
+
if(!process_info(pid,&info)) return 0;
|
|
80
|
+
birth(&info,started,sizeof(started));
|
|
81
|
+
if(strcmp(started,argv[4])) return 0;
|
|
82
|
+
if(info.bsd.pbi_uid!=getuid()) fail("Mac execution belongs to another user");
|
|
83
|
+
audit_token_t token={{0}}; token.val[5]=(uint32_t)pid; token.val[7]=(uint32_t)info.unique.version;
|
|
84
|
+
if(signal_token(&token,SIGKILL)!=0 && errno!=ESRCH) fail("Owned Mac process could not be stopped");
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
if(argc==3 && !strcmp(argv[1],"process")) {
|
|
88
|
+
pid_t pid=(pid_t)number(argv[2]); uint64_t id; struct process_info info={0};
|
|
89
|
+
if(!process_info(pid,&info) || !coalition(pid,&id)) { puts("null"); return 0; }
|
|
90
|
+
if(info.bsd.pbi_uid!=getuid()) fail("Mac execution belongs to another user");
|
|
91
|
+
time_t seconds=(time_t)info.bsd.pbi_start_tvsec; struct tm tm; char date[32];
|
|
92
|
+
gmtime_r(&seconds,&tm); strftime(date,sizeof(date),"%Y-%m-%dT%H:%M:%S",&tm);
|
|
93
|
+
printf("{\"id\":\"%"PRIu64"\",\"boot\":\"%s\",\"pid\":%d,\"ppid\":%u,\"pgid\":%u,\"owner\":%u,\"birth\":\"%s.%06"PRIu64"Z\",\"version\":%u}\n",id,boot,pid,info.bsd.pbi_ppid,info.bsd.pbi_pgid,getuid(),date,info.bsd.pbi_start_tvusec,(uint32_t)info.unique.version); return 0;
|
|
94
|
+
}
|
|
95
|
+
int all=argc==2 && !strcmp(argv[1],"all");
|
|
96
|
+
if(!all && argc<4) fail("Invalid Mac execution helper command");
|
|
97
|
+
uint64_t id=all?0:number(argv[2]);
|
|
98
|
+
// These one-shot jobs have no future-login plist. A changed kernel boot also
|
|
99
|
+
// proves every member and queued launch from the recorded boot has ended.
|
|
100
|
+
if(argc==4 && !strcmp(argv[1],"inspect") && strcmp(argv[3],boot)) { puts("{\"exists\":false,\"active\":0,\"members\":[]}"); return 0; }
|
|
101
|
+
if(!all) same_boot(argv[3]);
|
|
102
|
+
if(argc==7 && !strcmp(argv[1],"signal")) {
|
|
103
|
+
pid_t pid=(pid_t)number(argv[4]); uint64_t version=number(argv[5]), actual;
|
|
104
|
+
int signal=!strcmp(argv[6],"TERM")?SIGTERM:!strcmp(argv[6],"KILL")?SIGKILL:0;
|
|
105
|
+
if(!signal) fail("Invalid Mac execution signal");
|
|
106
|
+
struct process_info info={0};
|
|
107
|
+
if(!coalition(pid,&actual) || actual!=id || !process_info(pid,&info) || (uint32_t)info.unique.version!=version) return 0;
|
|
108
|
+
if(info.bsd.pbi_uid!=getuid()) fail("Mac execution belongs to another user");
|
|
109
|
+
audit_token_t token={{0}}; token.val[5]=(uint32_t)pid; token.val[7]=(uint32_t)version;
|
|
110
|
+
// The kernel compares the PID version while holding the process reference;
|
|
111
|
+
// a reused PID cannot receive this signal.
|
|
112
|
+
if(signal_token(&token,signal)!=0 && errno!=ESRCH) fail("Owned Mac execution could not be stopped");
|
|
113
|
+
return 0;
|
|
114
|
+
}
|
|
115
|
+
if(!all && (argc!=4 || strcmp(argv[1],"inspect"))) fail("Invalid Mac execution helper command");
|
|
116
|
+
uint64_t count=1; int exists=all?1:active(id,&count);
|
|
117
|
+
if(!exists || !count) { printf("{\"exists\":%s,\"active\":0,\"members\":[]}\n",exists?"true":"false"); return 0; }
|
|
118
|
+
int capacity=proc_listpids(PROC_UID_ONLY,getuid(),NULL,0)/(int)sizeof(pid_t)+1024;
|
|
119
|
+
if(capacity<=1024 || capacity>1000000) fail("Mac process enumeration is unavailable");
|
|
120
|
+
pid_t *pids=calloc((size_t)capacity,sizeof(pid_t));
|
|
121
|
+
struct process_info *rows=calloc((size_t)capacity,sizeof(struct process_info));
|
|
122
|
+
if(!pids || !rows) fail("Mac process enumeration could not allocate memory");
|
|
123
|
+
int bytes=proc_listpids(PROC_UID_ONLY,getuid(),pids,capacity*(int)sizeof(pid_t));
|
|
124
|
+
if(bytes<0 || bytes%(int)sizeof(pid_t)) fail("Mac process enumeration is unavailable");
|
|
125
|
+
int total=bytes/(int)sizeof(pid_t), found=0;
|
|
126
|
+
if(total<0 || total>=capacity) changed();
|
|
127
|
+
for(int i=0;i<total;i++) {
|
|
128
|
+
uint64_t candidate; if(pids[i]<=0 || (!all && (!coalition(pids[i],&candidate) || candidate!=id))) continue;
|
|
129
|
+
struct process_info row={0}, after={0};
|
|
130
|
+
if(!process_info(pids[i],&row) || (!all && (!coalition(pids[i],&candidate) || candidate!=id)) || !process_info(pids[i],&after)) continue;
|
|
131
|
+
if(row.unique.version!=after.unique.version) continue;
|
|
132
|
+
if(row.bsd.pbi_uid!=getuid()) fail("Mac execution membership includes a different user");
|
|
133
|
+
rows[found++]=row;
|
|
134
|
+
}
|
|
135
|
+
if(all) count=(uint64_t)found; else exists=active(id,&count);
|
|
136
|
+
// A new task missing from the snapshot is uncertainty, never empty success.
|
|
137
|
+
if(count>(uint64_t)found) changed();
|
|
138
|
+
printf("{\"exists\":%s,\"active\":%"PRIu64",\"members\":[",exists?"true":"false",count);
|
|
139
|
+
for(int i=0;count && i<found;i++) {
|
|
140
|
+
struct process_info *row=&rows[i]; time_t seconds=(time_t)row->bsd.pbi_start_tvsec; struct tm tm; char date[32];
|
|
141
|
+
gmtime_r(&seconds,&tm); strftime(date,sizeof(date),"%Y-%m-%dT%H:%M:%S",&tm);
|
|
142
|
+
printf("%s{\"pid\":%u,\"ppid\":%u,\"pgid\":%u,\"owner\":\"%u\",\"birth\":\"%s.%06"PRIu64"Z\",\"version\":%u}",i?",":"",row->bsd.pbi_pid,row->bsd.pbi_ppid,row->bsd.pbi_pgid,row->bsd.pbi_uid,date,row->bsd.pbi_start_tvusec,(uint32_t)row->unique.version);
|
|
143
|
+
}
|
|
144
|
+
puts("]}"); free(rows); free(pids); return 0;
|
|
145
|
+
}
|