• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/procd/trace2seccomp.uc

  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