1 #!/usr/bin/ucode -R 2 3 import { readfile, writefile, basename, unlink } from 'fs'; 4 5 const ACT_KILL = 'SCMP_ACT_KILL_PROCESS'; 6 const ACT_ALLOW = 'SCMP_ACT_ALLOW'; 7 8 function usage(name) { 9 if (name == 'trace2seccomp') 10 warn("usage: trace2seccomp [--merged|--two-phase] [-o out.json] <trace.ndjson>\n"); 11 else 12 warn(sprintf("usage: %s <program> [args...]\n", name)); 13 exit(1); 14 } 15 16 function shq(s) { 17 return "'" + replace(s, "'", "'\\''") + "'"; 18 } 19 20 function invoked_name() { 21 let cmd = readfile('/proc/self/cmdline'); 22 if (!cmd) 23 return basename(sourcepath()); 24 25 let parts = split(cmd, '\x00'); 26 while (length(parts) && parts[length(parts) - 1] == '') 27 pop(parts); 28 29 let idx = length(parts) - length(ARGV) - 1; 30 if (idx < 0) 31 return basename(sourcepath()); 32 33 return basename(parts[idx]); 34 } 35 36 function collect(ndjson, want_phase) { 37 let seen = {}; 38 39 for (let line in split(ndjson, '\n')) { 40 if (!length(line)) 41 continue; 42 43 let ev; 44 try { ev = json(line); } 45 catch (e) { continue; } 46 47 if (type(ev) != 'object' || ev.event != 'syscall' || !ev.syscall) 48 continue; 49 if (want_phase && ev.phase != want_phase) 50 continue; 51 52 seen[ev.syscall] = true; 53 } 54 55 return sort(keys(seen)); 56 } 57 58 function profile(names) { 59 return { 60 defaultAction: ACT_KILL, 61 syscalls: [ { names: names, action: ACT_ALLOW } ] 62 }; 63 } 64 65 function emit(obj, outfile) { 66 let text = sprintf("%.J\n", obj); 67 68 if (!outfile) { 69 print(text); 70 return; 71 } 72 73 if (writefile(outfile, text) == null) 74 die(sprintf("cannot write %s\n", outfile)); 75 } 76 77 function run_trace(prog, args) { 78 let tmp = sprintf("/tmp/.trace2seccomp.%d.ndjson", time()); 79 let cmd = "ujail -m trace -M " + shq(tmp) + " -- " + shq(prog); 80 81 for (let a in args) 82 cmd += " " + shq(a); 83 84 system(cmd); 85 86 let nd = readfile(tmp); 87 unlink(tmp); 88 89 return nd; 90 } 91 92 function run_live(name) { 93 if (!length(ARGV)) 94 usage(name); 95 96 let prog = ARGV[0]; 97 let nd = run_trace(prog, slice(ARGV, 1)); 98 if (nd == null) 99 die("no trace captured (did ujail run?)\n"); 100 101 let out = sprintf("/tmp/%s.%d.json", basename(prog), time()); 102 emit(profile(collect(nd, 'app')), out); 103 warn(sprintf("seccomp profile written to %s\n", out)); 104 } 105 106 function run_offline() { 107 let merged, two_phase, outfile, infile; 108 let i = 0; 109 110 while (i < length(ARGV)) { 111 let a = ARGV[i]; 112 if (a == '--merged') 113 merged = true; 114 else if (a == '--two-phase') 115 two_phase = true; 116 else if (a == '-o') 117 outfile = ARGV[++i]; 118 else 119 infile = a; 120 i++; 121 } 122 123 if (!infile) 124 usage('trace2seccomp'); 125 126 let nd = readfile(infile); 127 if (nd == null) 128 die(sprintf("cannot read %s\n", infile)); 129 130 if (two_phase) 131 emit({ predl: profile(collect(nd, null)), postdl: profile(collect(nd, 'app')) }, outfile); 132 else if (merged) 133 emit(profile(collect(nd, null)), outfile); 134 else 135 emit(profile(collect(nd, 'app')), outfile); 136 } 137 138 let self = invoked_name(); 139 140 if (self == 'utrace' || self == 'seccomp-trace') 141 run_live(self); 142 else 143 run_offline();
This page was automatically generated by LXR 0.3.1. • OpenWrt