this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Extend sys_sysctl() to get 'ps' somewhat working

+412 -16
+2 -1
src/kernel/emulation/linux/CMakeLists.txt
··· 5 5 cmake_policy(SET CMP0005 NEW) 6 6 enable_language(ASM) 7 7 8 - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -fvisibility=hidden -fPIC -ggdb -Wno-int-conversion") 8 + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -fvisibility=hidden -fPIC -fno-builtin -ggdb -Wno-int-conversion") 9 9 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -nostdlib") 10 10 11 11 add_definitions(-DBSDTHREAD_WRAP_LINUX_PTHREAD ··· 120 120 misc/thread_selfid.c 121 121 misc/proc_info.c 122 122 misc/sysctl.c 123 + misc/sysctl_proc.c 123 124 misc/getrlimit.c 124 125 misc/setrlimit.c 125 126 misc/gethostuuid.c
+13 -14
src/kernel/emulation/linux/misc/sysctl.c
··· 24 24 extern kern_return_t mach_port_deallocate(ipc_space_t task, mach_port_name_t name); 25 25 extern kern_return_t host_info(mach_port_name_t host, int itype, void* hinfo, mach_msg_type_number_t* count); 26 26 27 + struct kinfo_proc; 28 + extern int _sysctl_proc(int what, int flag, struct kinfo_proc* out, unsigned long* buflen); 29 + extern int _sysctl_procargs(int pid, char* buf, unsigned long* buflen); 30 + 27 31 /* Darling specific */ 28 32 enum { 29 33 _HW_PHYSICAL_CPU = 1000, ··· 165 169 } 166 170 case KERN_PROC: 167 171 { 168 - // Returns array of struct kinfo_proc 169 172 if (nlen < 4) 170 173 return -ENOTDIR; 171 - switch (name[2]) 172 - { 173 - case KERN_PROC_ALL: 174 - case KERN_PROC_PID: 175 - case KERN_PROC_TTY: 176 - case KERN_PROC_UID: 177 - case KERN_PROC_PGRP: 178 - case KERN_PROC_SESSION: 179 - case KERN_PROC_RUID: 180 - case KERN_PROC_LCID: 181 - default: 182 - return -ENOTDIR; 183 - } 174 + // Returns array of struct kinfo_proc 175 + return _sysctl_proc(name[2], name[3], (struct kinfo_proc*) old, oldlen); 176 + 177 + } 178 + case KERN_PROCARGS2: 179 + { 180 + if (nlen < 3) 181 + return -ENOTDIR; 182 + return _sysctl_procargs(name[2], (char*) old, oldlen); 184 183 } 185 184 case KERN_ARGMAX: 186 185 {
+391
src/kernel/emulation/linux/misc/sysctl_proc.c
··· 1 + #include <sys/sysctl.h> 2 + #include <sys/errno.h> 3 + #include "../dirent/getdirentries.h" 4 + #include "../unistd/close.h" 5 + #include "../unistd/read.h" 6 + #include "../unistd/getuid.h" 7 + #include "../unistd/getgid.h" 8 + #include "../fcntl/open.h" 9 + #include "../simple.h" 10 + 11 + #ifndef isdigit 12 + # define isdigit(c) (c >= '0' && c <= '9') 13 + #endif 14 + #ifndef DT_DIR 15 + # define DT_DIR 4 16 + #endif 17 + 18 + struct kinfo_proc_chain 19 + { 20 + struct kinfo_proc_chain* next; 21 + struct kinfo_proc kinfo; 22 + }; 23 + 24 + static struct kinfo_proc_chain* load_proc(const char* name, int what, int flag); 25 + static void free_chain(struct kinfo_proc_chain* chain); 26 + 27 + extern void free(void* ptr); 28 + extern void* malloc(__SIZE_TYPE__ len); 29 + extern __SIZE_TYPE__ strlen(const char* ptr); 30 + extern char* strcpy(char* dst, const char* src); 31 + extern void* memset(void*, int, __SIZE_TYPE__); 32 + extern void* memcpy(void* dest, const void*, __SIZE_TYPE__); 33 + extern char *strncpy(char *dest, const char *src, __SIZE_TYPE__ n); 34 + 35 + int _sysctl_proc(int what, int flag, struct kinfo_proc* out, unsigned long* buflen) 36 + { 37 + int fd, ret = 0; 38 + char dents[256]; 39 + long basep = 0; 40 + int nproc = 0; 41 + struct kinfo_proc_chain *first = NULL, *last = NULL; 42 + 43 + if (buflen == NULL) 44 + return -EFAULT; 45 + if (*buflen > 0 && out == NULL) 46 + return -EFAULT; 47 + 48 + fd = sys_open_nocancel("/proc", BSD_O_RDONLY | BSD_O_DIRECTORY, 0); 49 + if (fd < 0) 50 + return fd; 51 + 52 + while ((ret = sys_getdirentries(fd, (char*) dents, sizeof(dents), &basep)) > 0) 53 + { 54 + int pos = 0; 55 + 56 + while (pos < ret) 57 + { 58 + struct bsd_dirent* dent = (struct bsd_dirent*) &dents[pos]; 59 + struct kinfo_proc_chain* cur; 60 + // __simple_printf("Looking at %s\n", dent->d_name); 61 + 62 + if (dent->d_type != DT_DIR || !isdigit(dent->d_name[0])) 63 + { 64 + pos += dent->d_reclen; 65 + continue; 66 + } 67 + 68 + // Avoid loading process info unless really needed 69 + if (what != KERN_PROC_ALL || *buflen > 0) 70 + { 71 + cur = load_proc(dent->d_name, what, flag); 72 + 73 + if (cur != NULL) 74 + { 75 + nproc++; 76 + 77 + if (first == NULL) 78 + first = cur; 79 + if (last != NULL) 80 + last->next = cur; 81 + cur->next = NULL; 82 + last = cur; 83 + } 84 + } 85 + else 86 + nproc++; 87 + 88 + pos += dent->d_reclen; 89 + } 90 + } 91 + 92 + if (*buflen < nproc*sizeof(struct kinfo_proc)) 93 + { 94 + *buflen = nproc*sizeof(struct kinfo_proc); 95 + ret = out ? -ENOSPC : 0; 96 + } 97 + else 98 + { 99 + struct kinfo_proc_chain *next; 100 + int i; 101 + 102 + *buflen = nproc*sizeof(struct kinfo_proc); 103 + 104 + next = first; 105 + for (i = 0; next != NULL; i++) 106 + { 107 + memcpy(&out[i], &next->kinfo, sizeof(struct kinfo_proc)); 108 + next = next->next; 109 + } 110 + } 111 + 112 + free_chain(first); 113 + sys_close(fd); 114 + 115 + // __simple_printf("sysctl_proc returning %d, len %d\n", ret, *buflen); 116 + return ret; 117 + } 118 + 119 + static int read_string(const char* path, char* dst, int maxlen) 120 + { 121 + int fd, rd; 122 + 123 + fd = sys_open(path, BSD_O_RDONLY, 0); 124 + if (fd < 0) 125 + return fd; 126 + 127 + rd = sys_read(fd, dst, maxlen-1); 128 + if (rd >= 0) 129 + dst[rd] = '\0'; 130 + 131 + sys_close(fd); 132 + return rd >= 0; 133 + } 134 + 135 + static int read_int(const char* path, int* dst) 136 + { 137 + char buf[24]; 138 + 139 + if (read_string(path, buf, sizeof(buf)) < 0) 140 + return 0; 141 + 142 + *dst = __simple_atoi(buf, NULL); 143 + return 1; 144 + } 145 + 146 + static const char* next_stat_elem(char** buf) 147 + { 148 + char* start; 149 + 150 + start = *buf; 151 + 152 + if (!*start) 153 + return NULL; 154 + else if (*start == '(') 155 + { 156 + char* end; 157 + 158 + start++; 159 + end = start; 160 + 161 + while (*end != ')' && *end) 162 + end++; 163 + *end = '\0'; 164 + *buf = end+2; 165 + } 166 + else 167 + { 168 + char* end; 169 + 170 + end = start; 171 + while (*end != ' ' && *end) 172 + end++; 173 + *end = '\0'; 174 + *buf = end+1; 175 + } 176 + 177 + // __simple_printf("Next stat elem: %s\n", start); 178 + return start; 179 + } 180 + 181 + static void skip_stat_elems(char** buf, int count) 182 + { 183 + int i; 184 + for (i = 0; i < count; i++) 185 + next_stat_elem(buf); 186 + } 187 + 188 + static struct kinfo_proc_chain* load_proc(const char* name, int what, int flag) 189 + { 190 + char path[56]; 191 + char stat[1024]; 192 + char *statptr; 193 + const char* elem; 194 + struct kinfo_proc_chain* kinfo; 195 + static int uid = -1, gid = -1; 196 + 197 + __simple_sprintf(path, "/proc/%s/stat", name); 198 + 199 + kinfo = (struct kinfo_proc_chain*) malloc(sizeof(*kinfo)); 200 + memset(kinfo, 0, sizeof(*kinfo)); 201 + 202 + kinfo->kinfo.kp_proc.p_pid = __simple_atoi(name, NULL); 203 + 204 + if (!read_string(path, stat, sizeof(stat))) 205 + goto retnull; 206 + 207 + statptr = stat; 208 + skip_stat_elems(&statptr, 1); // skip pid 209 + 210 + #define READELEM() elem = next_stat_elem(&statptr); if (!elem) goto retnull 211 + 212 + // comm 213 + READELEM(); 214 + strncpy(kinfo->kinfo.kp_proc.p_comm, elem, sizeof(kinfo->kinfo.kp_proc.p_comm)); 215 + 216 + // process state 217 + READELEM(); 218 + switch (*elem) 219 + { 220 + case 'R': 221 + kinfo->kinfo.kp_proc.p_stat = SRUN; 222 + break; 223 + case 'S': 224 + case 'D': 225 + kinfo->kinfo.kp_proc.p_stat = SSLEEP; 226 + break; 227 + case 'T': 228 + kinfo->kinfo.kp_proc.p_stat = SSTOP; 229 + break; 230 + case 'Z': 231 + kinfo->kinfo.kp_proc.p_stat = SZOMB; 232 + break; 233 + default: 234 + kinfo->kinfo.kp_proc.p_stat = SSLEEP; 235 + } 236 + 237 + // ppid 238 + READELEM(); 239 + kinfo->kinfo.kp_eproc.e_ppid = __simple_atoi(elem, NULL); 240 + 241 + // pgid 242 + READELEM(); 243 + kinfo->kinfo.kp_eproc.e_pgid = __simple_atoi(elem, NULL); 244 + 245 + // sid 246 + READELEM(); 247 + if (what == KERN_PROC_SESSION) 248 + { 249 + int sid = __simple_atoi(elem, NULL); 250 + if (sid != flag) 251 + goto retnull; 252 + } 253 + 254 + // tty_nr 255 + READELEM(); 256 + kinfo->kinfo.kp_eproc.e_tdev = __simple_atoi(elem, NULL); 257 + if (kinfo->kinfo.kp_eproc.e_tdev != 0) 258 + kinfo->kinfo.kp_proc.p_flag |= P_CONTROLT; 259 + 260 + skip_stat_elems(&statptr, NULL); 261 + 262 + READELEM(); 263 + kinfo->kinfo.kp_proc.p_priority = __simple_atoi(elem, NULL); 264 + 265 + READELEM(); 266 + kinfo->kinfo.kp_proc.p_nice = __simple_atoi(elem, NULL); 267 + 268 + // In the container, everything is owned by us 269 + if (uid == -1 || gid == -1) 270 + { 271 + uid = sys_getuid(); 272 + gid = sys_getgid(); 273 + } 274 + 275 + kinfo->kinfo.kp_eproc.e_pcred.p_ruid = uid; 276 + kinfo->kinfo.kp_eproc.e_pcred.p_svuid = uid; 277 + kinfo->kinfo.kp_eproc.e_pcred.p_rgid = gid; 278 + kinfo->kinfo.kp_eproc.e_pcred.p_svgid = gid; 279 + kinfo->kinfo.kp_eproc.e_ucred.cr_uid = uid; 280 + 281 + switch (what) 282 + { 283 + case KERN_PROC_ALL: 284 + break; 285 + case KERN_PROC_PID: 286 + if (flag != kinfo->kinfo.kp_proc.p_pid) 287 + goto retnull; 288 + break; 289 + case KERN_PROC_TTY: 290 + if (flag != kinfo->kinfo.kp_eproc.e_tdev) 291 + goto retnull; 292 + break; 293 + case KERN_PROC_UID: 294 + if (flag != kinfo->kinfo.kp_eproc.e_ucred.cr_uid) 295 + goto retnull; 296 + break; 297 + case KERN_PROC_PGRP: 298 + if (flag != kinfo->kinfo.kp_eproc.e_pgid) 299 + goto retnull; 300 + break; 301 + case KERN_PROC_SESSION: 302 + // Not present in the struct 303 + // Apple plans to introduce ki_sid? 304 + // -> Evaluated above 305 + break; 306 + case KERN_PROC_RUID: 307 + if (flag != kinfo->kinfo.kp_eproc.e_pcred.p_ruid) 308 + goto retnull; 309 + break; 310 + case KERN_PROC_LCID: 311 + break; 312 + default: 313 + goto retnull; 314 + } 315 + 316 + return kinfo; 317 + retnull: 318 + free(kinfo); 319 + return NULL; 320 + } 321 + 322 + static void free_chain(struct kinfo_proc_chain* chain) 323 + { 324 + struct kinfo_proc_chain* next = chain; 325 + 326 + while (chain != NULL) 327 + { 328 + next = chain->next; 329 + free(chain); 330 + chain = next; 331 + } 332 + } 333 + 334 + int _sysctl_procargs(int pid, char* buf, unsigned long* buflen) 335 + { 336 + char path[56]; 337 + char cmdline[2048]; 338 + int argc = 0, i, arg0len = 0, argslen = 0; 339 + int totallen, ret = 0; 340 + 341 + __simple_sprintf(path, "/proc/%d/cmdline", pid); 342 + 343 + if (!read_string(path, cmdline, sizeof(cmdline))) 344 + return -ENOTDIR; 345 + 346 + if (!cmdline[0]) 347 + { 348 + int len; 349 + 350 + // Provide comm instead 351 + __simple_sprintf(path, "/proc/%d/comm", pid); 352 + 353 + if (!read_string(path, cmdline, sizeof(cmdline))) 354 + return -ENOTDIR; 355 + 356 + len = strlen(cmdline); 357 + cmdline[len-1] = '\0'; // comm ends with \r 358 + } 359 + 360 + for (i = 0; i < sizeof(cmdline)-1; i++) 361 + { 362 + if (!cmdline[i]) 363 + { 364 + argc++; 365 + if (argc == 1) 366 + arg0len = i; 367 + } 368 + if (i > 0 && !cmdline[i-1] && !cmdline[i]) 369 + { 370 + argslen = i; 371 + break; 372 + } 373 + } 374 + totallen = sizeof(int) + arg0len + 2 + argslen + 1; 375 + 376 + if (*buflen < totallen) 377 + { 378 + *buflen = totallen; 379 + ret = (buf) ? -ENOSPC : 0; 380 + } 381 + else 382 + { 383 + *buflen = totallen; 384 + memcpy(buf, &argc, sizeof(argc)); 385 + strcpy(buf+sizeof(argc), cmdline); // copy arg0 as executable_path (TODO: not 100% correct) 386 + buf[sizeof(argc)+arg0len+2] = 0; 387 + memcpy(buf+sizeof(argc)+arg0len+2, cmdline, argslen+1); 388 + } 389 + return 0; 390 + } 391 +
+6 -1
src/kernel/emulation/linux/simple.c
··· 15 15 return len; 16 16 } 17 17 18 + static inline int abs(int n) 19 + { 20 + return (n < 0) ? -n : n; 21 + } 22 + 18 23 void __simple_vsprintf(char* buf, const char* format, va_list vl) 19 24 { 20 25 while (*format) ··· 54 59 55 60 do 56 61 { 57 - temp[count++] = '0' + (num % 10); 62 + temp[count++] = '0' + abs(num % 10); 58 63 num /= 10; 59 64 } 60 65 while (num > 0);