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

Sources/procd/jail/seccomp-inject.c

  1 /*
  2  * Apply a compiled cBPF seccomp filter to a freshly-execve'd workload by
  3  * injecting prctl(PR_SET_NO_NEW_PRIVS) and seccomp(SET_MODE_FILTER) into the
  4  * tracee via ptrace. The tracee does PTRACE_TRACEME before its final execve;
  5  * the parent catches the post-execve stop (before the workload's first
  6  * userspace instruction), pokes the filter into the tracee's stack, drives the
  7  * two syscalls by single-stepping a temporary trap instruction at the program
  8  * counter, restores the saved registers and code, then detaches. This arms the
  9  * filter for statically and dynamically linked workloads alike, closing the
 10  * gap left by an LD_PRELOAD-based installer (which static binaries ignore).
 11  *
 12  * Copyright (C) 2026 Daniel Golle <daniel@makrotopia.org>
 13  *
 14  * This program is free software; you can redistribute it and/or modify
 15  * it under the terms of the GNU Lesser General Public License version 2.1
 16  * as published by the Free Software Foundation
 17  *
 18  * This program is distributed in the hope that it will be useful,
 19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 21  * GNU General Public License for more details.
 22  */
 23 #define _GNU_SOURCE
 24 #include <errno.h>
 25 #include <fcntl.h>
 26 #include <signal.h>
 27 #include <stdint.h>
 28 #include <stdio.h>
 29 #include <string.h>
 30 #include <unistd.h>
 31 #include <sys/ptrace.h>
 32 #include <sys/uio.h>
 33 #include <sys/user.h>
 34 #include <sys/wait.h>
 35 #include <linux/filter.h>
 36 #include <linux/seccomp.h>
 37 #include <sys/prctl.h>
 38 #include <sys/syscall.h>
 39 #include <limits.h>
 40 
 41 #include "log.h"
 42 #include "seccomp-inject.h"
 43 #include "elf.h"
 44 
 45 #ifndef PR_SET_NO_NEW_PRIVS
 46 #define PR_SET_NO_NEW_PRIVS 38
 47 #endif
 48 #ifndef SECCOMP_SET_MODE_FILTER
 49 #define SECCOMP_SET_MODE_FILTER 1
 50 #endif
 51 #ifndef AT_NULL
 52 #define AT_NULL 0
 53 #endif
 54 #ifndef AT_ENTRY
 55 #define AT_ENTRY 9
 56 #endif
 57 #ifndef AT_BASE
 58 #define AT_BASE 7
 59 #endif
 60 #ifndef NT_PRSTATUS
 61 #define NT_PRSTATUS 1
 62 #endif
 63 #ifndef NT_ARM_SYSTEM_CALL
 64 #define NT_ARM_SYSTEM_CALL 0x404
 65 #endif
 66 #ifndef PTRACE_SET_SYSCALL
 67 #define PTRACE_SET_SYSCALL 23
 68 #endif
 69 
 70 #if defined(__x86_64__)
 71 typedef struct user_regs_struct inj_regs;
 72 #define INJ_SYSCALL_ASM "syscall"
 73 #define INJ_BP_ASM      "int3"
 74 static unsigned long inj_pc(const inj_regs *r)
 75 {
 76         return r->rip;
 77 }
 78 
 79 static void inj_set_pc(inj_regs *r, unsigned long pc)
 80 {
 81         r->rip = pc;
 82 }
 83 
 84 static unsigned long inj_sp(const inj_regs *r)
 85 {
 86         return r->rsp;
 87 }
 88 
 89 static long inj_ret(const inj_regs *r)
 90 {
 91         return r->rax;
 92 }
 93 
 94 static void inj_clear_restart(inj_regs *r)
 95 {
 96         r->orig_rax = (unsigned long)-1;
 97 }
 98 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
 99                          long a3, long a4, long a5)
100 {
101         r->rax = nr;
102         r->orig_rax = nr;
103         r->rdi = a0;
104         r->rsi = a1;
105         r->rdx = a2;
106         r->r10 = a3;
107         r->r8 = a4;
108         r->r9 = a5;
109 }
110 
111 static void inj_get_call(const inj_regs *r, long *nr, long *args)
112 {
113         *nr = r->orig_rax;
114         args[0] = r->rdi;
115         args[1] = r->rsi;
116         args[2] = r->rdx;
117         args[3] = r->r10;
118         args[4] = r->r8;
119         args[5] = r->r9;
120 }
121 
122 #elif defined(__i386__)
123 typedef struct user_regs_struct inj_regs;
124 #define INJ_SYSCALL_ASM "int $0x80"
125 #define INJ_BP_ASM      "int3"
126 static unsigned long inj_pc(const inj_regs *r)
127 {
128         return r->eip;
129 }
130 
131 static void inj_set_pc(inj_regs *r, unsigned long pc)
132 {
133         r->eip = pc;
134 }
135 
136 static unsigned long inj_sp(const inj_regs *r)
137 {
138         return r->esp;
139 }
140 
141 static long inj_ret(const inj_regs *r)
142 {
143         return r->eax;
144 }
145 
146 static void inj_clear_restart(inj_regs *r)
147 {
148         r->orig_eax = (unsigned long)-1;
149 }
150 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
151                          long a3, long a4, long a5)
152 {
153         r->eax = nr;
154         r->orig_eax = nr;
155         r->ebx = a0;
156         r->ecx = a1;
157         r->edx = a2;
158         r->esi = a3;
159         r->edi = a4;
160         r->ebp = a5;
161 }
162 
163 static void inj_get_call(const inj_regs *r, long *nr, long *args)
164 {
165         *nr = r->orig_eax;
166         args[0] = r->ebx;
167         args[1] = r->ecx;
168         args[2] = r->edx;
169         args[3] = r->esi;
170         args[4] = r->edi;
171         args[5] = r->ebp;
172 }
173 
174 #elif defined(__aarch64__)
175 typedef struct { unsigned long long regs[31], sp, pc, pstate; } inj_regs;
176 #define INJ_SYSCALL_ASM "svc #0"
177 #define INJ_BP_ASM      "brk #0"
178 static unsigned long inj_pc(const inj_regs *r)
179 {
180         return r->pc;
181 }
182 
183 static void inj_set_pc(inj_regs *r, unsigned long pc)
184 {
185         r->pc = pc;
186 }
187 
188 static unsigned long inj_sp(const inj_regs *r)
189 {
190         return r->sp;
191 }
192 
193 static long inj_ret(const inj_regs *r)
194 {
195         return r->regs[0];
196 }
197 
198 static void inj_clear_restart(inj_regs *r)
199 {
200         (void)r;
201 }
202 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
203                          long a3, long a4, long a5)
204 {
205         r->regs[8] = nr;
206         r->regs[0] = a0;
207         r->regs[1] = a1;
208         r->regs[2] = a2;
209         r->regs[3] = a3;
210         r->regs[4] = a4;
211         r->regs[5] = a5;
212 }
213 
214 static void inj_get_call(const inj_regs *r, long *nr, long *args)
215 {
216         *nr = r->regs[8];
217         args[0] = r->regs[0];
218         args[1] = r->regs[1];
219         args[2] = r->regs[2];
220         args[3] = r->regs[3];
221         args[4] = r->regs[4];
222         args[5] = r->regs[5];
223 }
224 
225 #elif defined(__arm__)
226 typedef struct { unsigned long uregs[18]; } inj_regs;
227 #define INJ_SYSCALL_ASM "svc #0"
228 static unsigned long inj_pc(const inj_regs *r)
229 {
230         return r->uregs[15];
231 }
232 
233 static void inj_set_pc(inj_regs *r, unsigned long pc)
234 {
235         r->uregs[15] = pc;
236 }
237 
238 static unsigned long inj_sp(const inj_regs *r)
239 {
240         return r->uregs[13];
241 }
242 
243 static long inj_ret(const inj_regs *r)
244 {
245         return r->uregs[0];
246 }
247 
248 static void inj_clear_restart(inj_regs *r) __attribute__((unused));
249 static void inj_clear_restart(inj_regs *r)
250 {
251         (void)r;
252 }
253 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
254                          long a3, long a4, long a5)
255 {
256         r->uregs[7] = nr;
257         r->uregs[0] = a0;
258         r->uregs[1] = a1;
259         r->uregs[2] = a2;
260         r->uregs[3] = a3;
261         r->uregs[4] = a4;
262         r->uregs[5] = a5;
263 }
264 
265 static void inj_get_call(const inj_regs *r, long *nr, long *args)
266 {
267         *nr = r->uregs[7];
268         args[0] = r->uregs[0];
269         args[1] = r->uregs[1];
270         args[2] = r->uregs[2];
271         args[3] = r->uregs[3];
272         args[4] = r->uregs[4];
273         args[5] = r->uregs[5];
274 }
275 
276 static int inj_thumb(const inj_regs *r)
277 {
278         return (r->uregs[16] >> 5) & 1;
279 }
280 
281 #elif defined(__riscv) && __riscv_xlen == 64
282 typedef struct {
283         unsigned long pc, ra, sp, gp, tp, t0, t1, t2, s0, s1;
284         unsigned long a0, a1, a2, a3, a4, a5, a6, a7;
285         unsigned long s2, s3, s4, s5, s6, s7, s8, s9, s10, s11;
286         unsigned long t3, t4, t5, t6;
287 } inj_regs;
288 #define INJ_SYSCALL_ASM "ecall"
289 #define INJ_BP_ASM      "ebreak"
290 #define INJ_NO_SINGLESTEP       1
291 static unsigned long inj_pc(const inj_regs *r)
292 {
293         return r->pc;
294 }
295 
296 static void inj_set_pc(inj_regs *r, unsigned long pc)
297 {
298         r->pc = pc;
299 }
300 
301 static unsigned long inj_sp(const inj_regs *r)
302 {
303         return r->sp;
304 }
305 
306 static long inj_ret(const inj_regs *r)
307 {
308         return r->a0;
309 }
310 
311 static void inj_clear_restart(inj_regs *r)
312 {
313         (void)r;
314 }
315 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
316                          long a3, long a4, long a5)
317 {
318         r->a7 = nr;
319         r->a0 = a0;
320         r->a1 = a1;
321         r->a2 = a2;
322         r->a3 = a3;
323         r->a4 = a4;
324         r->a5 = a5;
325 }
326 
327 static void inj_get_call(const inj_regs *r, long *nr, long *args)
328 {
329         *nr = r->a7;
330         args[0] = r->a0;
331         args[1] = r->a1;
332         args[2] = r->a2;
333         args[3] = r->a3;
334         args[4] = r->a4;
335         args[5] = r->a5;
336 }
337 
338 #elif defined(__loongarch__) && __loongarch_grlen == 64
339 typedef struct { unsigned long regs[32], orig_a0, csr_era, csr_badv, reserved[10]; } inj_regs;
340 #define INJ_SYSCALL_ASM "syscall 0"
341 #define INJ_BP_ASM      "break 0"
342 #define INJ_NO_SINGLESTEP       1
343 static unsigned long inj_pc(const inj_regs *r)
344 {
345         return r->csr_era;
346 }
347 
348 static void inj_set_pc(inj_regs *r, unsigned long pc)
349 {
350         r->csr_era = pc;
351 }
352 
353 static unsigned long inj_sp(const inj_regs *r)
354 {
355         return r->regs[3];
356 }
357 
358 static long inj_ret(const inj_regs *r)
359 {
360         return r->regs[4];
361 }
362 
363 static void inj_clear_restart(inj_regs *r)
364 {
365         (void)r;
366 }
367 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
368                          long a3, long a4, long a5)
369 {
370         r->regs[11] = nr;
371         r->regs[4] = a0;
372         r->regs[5] = a1;
373         r->regs[6] = a2;
374         r->regs[7] = a3;
375         r->regs[8] = a4;
376         r->regs[9] = a5;
377 }
378 
379 static void inj_get_call(const inj_regs *r, long *nr, long *args)
380 {
381         *nr = r->regs[11];
382         args[0] = r->regs[4];
383         args[1] = r->regs[5];
384         args[2] = r->regs[6];
385         args[3] = r->regs[7];
386         args[4] = r->regs[8];
387         args[5] = r->regs[9];
388 }
389 
390 #elif defined(__mips__)
391 #ifndef ELF_NGREG
392 #define ELF_NGREG 45
393 #endif
394 #if _MIPS_SIM == _ABIO32
395 #define MIPS_EF_V0      8
396 #define MIPS_EF_A0      10
397 #define MIPS_EF_SP      35
398 #define MIPS_EF_A3      13
399 #define MIPS_EF_EPC     40
400 #else
401 #define MIPS_EF_V0      2
402 #define MIPS_EF_A0      4
403 #define MIPS_EF_SP      29
404 #define MIPS_EF_A3      7
405 #define MIPS_EF_EPC     34
406 #endif
407 typedef struct { unsigned long gregs[ELF_NGREG]; } inj_regs;
408 #define INJ_SYSCALL_ASM "syscall"
409 #define INJ_BP_ASM      "break"
410 #define INJ_NO_SINGLESTEP       1
411 static unsigned long inj_pc(const inj_regs *r)
412 {
413         return r->gregs[MIPS_EF_EPC];
414 }
415 
416 static void inj_set_pc(inj_regs *r, unsigned long pc)
417 {
418         r->gregs[MIPS_EF_EPC] = pc;
419 }
420 
421 static unsigned long inj_sp(const inj_regs *r)
422 {
423         return r->gregs[MIPS_EF_SP];
424 }
425 
426 #if _MIPS_SIM == _ABIO32
427 static void inj_set_sp(inj_regs *r, unsigned long sp)
428 {
429         r->gregs[MIPS_EF_SP] = sp;
430 }
431 #endif
432 
433 static long inj_ret(const inj_regs *r)
434 {
435         if (r->gregs[MIPS_EF_A3])
436                 return -(long)r->gregs[MIPS_EF_V0];
437 
438         return r->gregs[MIPS_EF_V0];
439 }
440 
441 static void inj_clear_restart(inj_regs *r)
442 {
443         (void)r;
444 }
445 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
446                          long a3, long a4, long a5)
447 {
448         r->gregs[MIPS_EF_V0] = nr;
449         r->gregs[MIPS_EF_A0] = a0;
450         r->gregs[MIPS_EF_A0 + 1] = a1;
451         r->gregs[MIPS_EF_A0 + 2] = a2;
452         r->gregs[MIPS_EF_A0 + 3] = a3;
453 #if _MIPS_SIM != _ABIO32
454         r->gregs[MIPS_EF_A0 + 4] = a4;
455         r->gregs[MIPS_EF_A0 + 5] = a5;
456         r->gregs[MIPS_EF_A0 + 6] = 0;
457         r->gregs[MIPS_EF_A0 + 7] = 0;
458 #else
459         (void)a4;
460         (void)a5;
461 #endif
462 }
463 
464 static void inj_get_call(const inj_regs *r, long *nr, long *args)
465 {
466         *nr = r->gregs[MIPS_EF_V0];
467         args[0] = r->gregs[MIPS_EF_A0];
468         args[1] = r->gregs[MIPS_EF_A0 + 1];
469         args[2] = r->gregs[MIPS_EF_A0 + 2];
470         args[3] = r->gregs[MIPS_EF_A0 + 3];
471 #if _MIPS_SIM != _ABIO32
472         args[4] = r->gregs[MIPS_EF_A0 + 4];
473         args[5] = r->gregs[MIPS_EF_A0 + 5];
474 #else
475         args[4] = 0;
476         args[5] = 0;
477 #endif
478 }
479 
480 #elif defined(__powerpc64__)
481 typedef struct {
482         unsigned long gpr[32];
483         unsigned long nip, msr, orig_gpr3, ctr, link, xer, ccr, softe;
484         unsigned long trap, dar, dsisr, result;
485 } inj_regs;
486 #define INJ_SYSCALL_ASM "sc"
487 #define INJ_BP_ASM      "trap"
488 static unsigned long inj_pc(const inj_regs *r)
489 {
490         return r->nip;
491 }
492 
493 static void inj_set_pc(inj_regs *r, unsigned long pc)
494 {
495         r->nip = pc;
496 }
497 
498 static unsigned long inj_sp(const inj_regs *r)
499 {
500         return r->gpr[1];
501 }
502 
503 static long inj_ret(const inj_regs *r)
504 {
505         if (r->ccr & 0x10000000UL)
506                 return -(long)r->gpr[3];
507         return r->gpr[3];
508 }
509 
510 static void inj_clear_restart(inj_regs *r)
511 {
512         (void)r;
513 }
514 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
515                          long a3, long a4, long a5)
516 {
517         r->gpr[0] = nr;
518         r->gpr[3] = a0;
519         r->gpr[4] = a1;
520         r->gpr[5] = a2;
521         r->gpr[6] = a3;
522         r->gpr[7] = a4;
523         r->gpr[8] = a5;
524 }
525 
526 static void inj_get_call(const inj_regs *r, long *nr, long *args)
527 {
528         *nr = r->gpr[0];
529         args[0] = r->gpr[3];
530         args[1] = r->gpr[4];
531         args[2] = r->gpr[5];
532         args[3] = r->gpr[6];
533         args[4] = r->gpr[7];
534         args[5] = r->gpr[8];
535 }
536 
537 #elif defined(__powerpc__)
538 typedef struct {
539         unsigned long gpr[32];
540         unsigned long nip, msr, orig_gpr3, ctr, link, xer, ccr, mq;
541         unsigned long trap, dar, dsisr, result;
542 } inj_regs;
543 #define INJ_SYSCALL_ASM "sc"
544 #define INJ_BP_ASM      "trap"
545 static unsigned long inj_pc(const inj_regs *r)
546 {
547         return r->nip;
548 }
549 
550 static void inj_set_pc(inj_regs *r, unsigned long pc)
551 {
552         r->nip = pc;
553 }
554 
555 static unsigned long inj_sp(const inj_regs *r)
556 {
557         return r->gpr[1];
558 }
559 
560 static long inj_ret(const inj_regs *r)
561 {
562         if (r->ccr & 0x10000000UL)
563                 return -(long)r->gpr[3];
564         return r->gpr[3];
565 }
566 
567 static void inj_clear_restart(inj_regs *r)
568 {
569         (void)r;
570 }
571 static void inj_set_call(inj_regs *r, long nr, long a0, long a1, long a2,
572                          long a3, long a4, long a5)
573 {
574         r->gpr[0] = nr;
575         r->gpr[3] = a0;
576         r->gpr[4] = a1;
577         r->gpr[5] = a2;
578         r->gpr[6] = a3;
579         r->gpr[7] = a4;
580         r->gpr[8] = a5;
581 }
582 
583 static void inj_get_call(const inj_regs *r, long *nr, long *args)
584 {
585         *nr = r->gpr[0];
586         args[0] = r->gpr[3];
587         args[1] = r->gpr[4];
588         args[2] = r->gpr[5];
589         args[3] = r->gpr[6];
590         args[4] = r->gpr[7];
591         args[5] = r->gpr[8];
592 }
593 
594 #else
595 #error "unsupported architecture for seccomp ptrace injection"
596 #endif
597 
598 #if defined(__arm__)
599 __asm__ (
600         ".pushsection .text\n"
601         ".arm\n"
602         ".globl inj_syscall_insn_arm\ninj_syscall_insn_arm:\n\t" INJ_SYSCALL_ASM "\n"
603         ".globl inj_syscall_insn_arm_end\ninj_syscall_insn_arm_end:\n"
604         ".globl inj_bp_insn_arm\ninj_bp_insn_arm:\n\t.inst 0xe7f001f0\n"
605         ".globl inj_bp_insn_arm_end\ninj_bp_insn_arm_end:\n"
606         ".thumb\n"
607         ".globl inj_syscall_insn_thumb\ninj_syscall_insn_thumb:\n\t" INJ_SYSCALL_ASM "\n"
608         ".globl inj_syscall_insn_thumb_end\ninj_syscall_insn_thumb_end:\n"
609         ".globl inj_bp_insn_thumb\ninj_bp_insn_thumb:\n\t.inst.n 0xde01\n"
610         ".globl inj_bp_insn_thumb_end\ninj_bp_insn_thumb_end:\n"
611         ".popsection\n"
612 );
613 extern const unsigned char inj_syscall_insn_arm[], inj_syscall_insn_arm_end[];
614 extern const unsigned char inj_syscall_insn_thumb[], inj_syscall_insn_thumb_end[];
615 extern const unsigned char inj_bp_insn_arm[], inj_bp_insn_arm_end[];
616 extern const unsigned char inj_bp_insn_thumb[], inj_bp_insn_thumb_end[];
617 
618 #define INJ_INSN_MAX            16
619 #else
620 __asm__ (
621         ".pushsection .text\n"
622         ".globl inj_syscall_insn\ninj_syscall_insn:\n\t" INJ_SYSCALL_ASM "\n"
623         ".globl inj_syscall_insn_end\ninj_syscall_insn_end:\n"
624         ".globl inj_bp_insn\ninj_bp_insn:\n\t" INJ_BP_ASM "\n"
625         ".globl inj_bp_insn_end\ninj_bp_insn_end:\n"
626         ".popsection\n"
627 );
628 extern const unsigned char inj_syscall_insn[], inj_syscall_insn_end[];
629 extern const unsigned char inj_bp_insn[], inj_bp_insn_end[];
630 
631 #define inj_syscall_len()       ((size_t)(inj_syscall_insn_end - inj_syscall_insn))
632 #define inj_bp_len()            ((size_t)(inj_bp_insn_end - inj_bp_insn))
633 #define INJ_INSN_MAX            16
634 #endif
635 
636 static int inj_getregs(pid_t pid, inj_regs *regs)
637 {
638         struct iovec iov;
639 
640         iov.iov_base = regs;
641         iov.iov_len = sizeof(*regs);
642 
643         return ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, &iov);
644 }
645 
646 static int inj_setregs(pid_t pid, inj_regs *regs)
647 {
648         struct iovec iov;
649 
650         iov.iov_base = regs;
651         iov.iov_len = sizeof(*regs);
652 
653         return ptrace(PTRACE_SETREGSET, pid, (void *)NT_PRSTATUS, &iov);
654 }
655 
656 int seccomp_read_syscall(pid_t pid, long *nr, long *args)
657 {
658         inj_regs regs;
659 
660         if (inj_getregs(pid, &regs))
661                 return -1;
662 
663         inj_get_call(&regs, nr, args);
664 
665         return 0;
666 }
667 
668 static int inj_poke(pid_t pid, unsigned long addr, const void *src, size_t len)
669 {
670         unsigned long word;
671         size_t off, chunk;
672 
673         for (off = 0; off < len; off += sizeof(long)) {
674                 chunk = (len - off < sizeof(long)) ? (len - off) : sizeof(long);
675                 errno = 0;
676                 word = ptrace(PTRACE_PEEKTEXT, pid, (void *)(addr + off), 0);
677                 if (word == (unsigned long)-1 && errno)
678                         return -1;
679                 memcpy(&word, (const char *)src + off, chunk);
680                 if (ptrace(PTRACE_POKETEXT, pid, (void *)(addr + off), (void *)word))
681                         return -1;
682         }
683 
684         return 0;
685 }
686 
687 static int inj_peek(pid_t pid, unsigned long addr, void *dst, size_t len)
688 {
689         unsigned long word;
690         size_t off, chunk;
691 
692         for (off = 0; off < len; off += sizeof(long)) {
693                 chunk = (len - off < sizeof(long)) ? (len - off) : sizeof(long);
694                 errno = 0;
695                 word = ptrace(PTRACE_PEEKTEXT, pid, (void *)(addr + off), 0);
696                 if (word == (unsigned long)-1 && errno)
697                         return -1;
698                 memcpy((char *)dst + off, &word, chunk);
699         }
700 
701         return 0;
702 }
703 
704 #if !defined(__arm__)
705 #ifdef INJ_NO_SINGLESTEP
706 static int inj_step(pid_t pid, unsigned long pc, int *status)
707 {
708         unsigned long bpaddr = pc + inj_syscall_len();
709         unsigned char saved[INJ_INSN_MAX];
710         size_t bplen = inj_bp_len();
711         int rc = -1;
712 
713         if (inj_peek(pid, bpaddr, saved, bplen))
714                 return -1;
715         if (inj_poke(pid, bpaddr, inj_bp_insn, bplen))
716                 return -1;
717 
718         if (ptrace(PTRACE_CONT, pid, 0, 0))
719                 goto out;
720         if (waitpid(pid, status, 0) < 0)
721                 goto out;
722         rc = 0;
723 
724 out:
725         inj_poke(pid, bpaddr, saved, bplen);
726         return rc;
727 }
728 #else
729 static int inj_step(pid_t pid, unsigned long pc, int *status)
730 {
731         (void)pc;
732 
733         if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0))
734                 return -1;
735         if (waitpid(pid, status, 0) < 0)
736                 return -1;
737 
738         return 0;
739 }
740 #endif
741 
742 static int inj_call(pid_t pid, const inj_regs *base, unsigned long pc,
743                     long nr, long a0, long a1, long a2,
744                     long a3, long a4, long a5, long *ret)
745 {
746         inj_regs regs;
747         int status;
748 #if defined(__mips__) && _MIPS_SIM == _ABIO32
749         unsigned long scratch;
750         unsigned long stkargs[4];
751 #endif
752 
753         for (;;) {
754                 regs = *base;
755                 inj_set_pc(&regs, pc);
756                 inj_set_call(&regs, nr, a0, a1, a2, a3, a4, a5);
757 #if defined(__mips__) && _MIPS_SIM == _ABIO32
758                 scratch = (inj_sp(base) - 256) & ~0xfUL;
759                 stkargs[0] = a4;
760                 stkargs[1] = a5;
761                 stkargs[2] = 0;
762                 stkargs[3] = 0;
763                 inj_set_sp(&regs, scratch);
764                 if (inj_poke(pid, scratch + 16, stkargs, sizeof(stkargs)))
765                         return -1;
766 #endif
767                 if (inj_setregs(pid, &regs))
768                         return -1;
769 
770                 if (inj_step(pid, pc, &status))
771                         return -1;
772                 if (WIFEXITED(status) || WIFSIGNALED(status))
773                         return -1;
774                 if (inj_getregs(pid, &regs))
775                         return -1;
776                 if (inj_pc(&regs) != pc)
777                         break;
778         }
779 
780         *ret = inj_ret(&regs);
781 
782         return 0;
783 }
784 #endif
785 
786 static int read_auxv(pid_t pid, unsigned long type, unsigned long *val)
787 {
788         char path[64];
789         unsigned long pair[2];
790         int fd;
791         ssize_t n;
792         int ret = -1;
793 
794         snprintf(path, sizeof(path), "/proc/%d/auxv", (int)pid);
795         fd = open(path, O_RDONLY | O_CLOEXEC);
796         if (fd < 0)
797                 return -1;
798 
799         while ((n = read(fd, pair, sizeof(pair))) == (ssize_t)sizeof(pair)) {
800                 if (pair[0] == type) {
801                         *val = pair[1];
802                         ret = 0;
803                         break;
804                 }
805                 if (pair[0] == AT_NULL)
806                         break;
807         }
808 
809         close(fd);
810         return ret;
811 }
812 
813 #if defined(__arm__)
814 
815 static int arm_thumb_at(unsigned long entry)
816 {
817         return (int)(entry & 1UL);
818 }
819 
820 static const unsigned char *arm_bp_insn(int thumb, size_t *len)
821 {
822         if (thumb) {
823                 *len = (size_t)(inj_bp_insn_thumb_end - inj_bp_insn_thumb);
824                 return inj_bp_insn_thumb;
825         }
826         *len = (size_t)(inj_bp_insn_arm_end - inj_bp_insn_arm);
827         return inj_bp_insn_arm;
828 }
829 
830 static const unsigned char *arm_syscall_insn(int thumb, size_t *len)
831 {
832         if (thumb) {
833                 *len = (size_t)(inj_syscall_insn_thumb_end - inj_syscall_insn_thumb);
834                 return inj_syscall_insn_thumb;
835         }
836         *len = (size_t)(inj_syscall_insn_arm_end - inj_syscall_insn_arm);
837         return inj_syscall_insn_arm;
838 }
839 
840 static int inj_call_arm(pid_t pid, const inj_regs *base, unsigned long pc,
841                         int thumb, long nr, long a0, long a1, long a2,
842                         long a3, long a4, long a5, long *ret)
843 {
844         const unsigned char *sci, *bpi;
845         size_t scilen, bpilen;
846         unsigned char saved[INJ_INSN_MAX];
847         inj_regs regs;
848         int status;
849 
850         sci = arm_syscall_insn(thumb, &scilen);
851         bpi = arm_bp_insn(thumb, &bpilen);
852 
853         if (inj_peek(pid, pc, saved, scilen + bpilen))
854                 return -1;
855         if (inj_poke(pid, pc, sci, scilen))
856                 return -1;
857         if (inj_poke(pid, pc + scilen, bpi, bpilen))
858                 goto restore;
859 
860         regs = *base;
861         inj_set_pc(&regs, pc);
862         inj_set_call(&regs, nr, a0, a1, a2, a3, a4, a5);
863         if (inj_setregs(pid, &regs))
864                 goto restore;
865 
866         if (ptrace(PTRACE_CONT, pid, 0, 0))
867                 goto restore;
868         if (waitpid(pid, &status, 0) < 0)
869                 goto restore;
870         if (!WIFSTOPPED(status))
871                 goto restore;
872 
873         if (inj_getregs(pid, &regs))
874                 goto restore;
875 
876         inj_poke(pid, pc, saved, scilen + bpilen);
877         *ret = inj_ret(&regs);
878 
879         return 0;
880 
881 restore:
882         inj_poke(pid, pc, saved, scilen + bpilen);
883         return -1;
884 }
885 
886 static int seccomp_run_to_entry_arm(pid_t pid)
887 {
888         const unsigned char *bp;
889         size_t bplen;
890         unsigned char saved[INJ_INSN_MAX];
891         unsigned long entry, addr;
892         inj_regs regs;
893         int status, sig = 0, thumb;
894 
895         if (read_auxv(pid, AT_ENTRY, &entry)) {
896                 ERROR("seccomp-inject: cannot read AT_ENTRY: %m\n");
897                 return -1;
898         }
899 
900         thumb = arm_thumb_at(entry);
901         addr = entry & ~1UL;
902         bp = arm_bp_insn(thumb, &bplen);
903 
904         if (inj_peek(pid, addr, saved, bplen)) {
905                 ERROR("seccomp-inject: read entry: %m\n");
906                 return -1;
907         }
908         if (inj_poke(pid, addr, bp, bplen)) {
909                 ERROR("seccomp-inject: poke entry breakpoint: %m\n");
910                 return -1;
911         }
912 
913         for (;;) {
914                 if (ptrace(PTRACE_CONT, pid, 0, (void *)(long)sig)) {
915                         ERROR("seccomp-inject: PTRACE_CONT to entry: %m\n");
916                         goto restore;
917                 }
918                 if (waitpid(pid, &status, 0) < 0) {
919                         ERROR("seccomp-inject: waitpid to entry: %m\n");
920                         goto restore;
921                 }
922                 if (!WIFSTOPPED(status)) {
923                         ERROR("seccomp-inject: workload exited before entry\n");
924                         return -1;
925                 }
926                 if (WSTOPSIG(status) == SIGTRAP)
927                         break;
928                 sig = WSTOPSIG(status);
929         }
930 
931         if (inj_getregs(pid, &regs)) {
932                 ERROR("seccomp-inject: GETREGSET at entry: %m\n");
933                 goto restore;
934         }
935         inj_set_pc(&regs, addr);
936         if (inj_setregs(pid, &regs)) {
937                 ERROR("seccomp-inject: SETREGSET at entry: %m\n");
938                 goto restore;
939         }
940         inj_poke(pid, addr, saved, bplen);
941 
942         return 0;
943 
944 restore:
945         inj_poke(pid, addr, saved, bplen);
946         return -1;
947 }
948 
949 static int seccomp_inject_arm(pid_t pid, struct sock_fprog *prog)
950 {
951         inj_regs saved;
952         struct sock_fprog rprog;
953         unsigned long sp, pc, filter_addr, prog_addr;
954         size_t filterlen;
955         long ret;
956         int thumb;
957 
958         if (inj_getregs(pid, &saved)) {
959                 ERROR("seccomp-inject: GETREGSET: %m\n");
960                 return -1;
961         }
962 
963         thumb = inj_thumb(&saved);
964 
965         pc = inj_pc(&saved);
966         sp = inj_sp(&saved);
967         filterlen = (size_t)prog->len * sizeof(struct sock_filter);
968 
969         filter_addr = (sp - 4096 - filterlen - sizeof(rprog)) & ~0xfUL;
970         prog_addr = (filter_addr + filterlen + 0xf) & ~0xfUL;
971 
972         if (inj_poke(pid, filter_addr, prog->filter, filterlen)) {
973                 ERROR("seccomp-inject: poke filter: %m\n");
974                 return -1;
975         }
976 
977         rprog.len = prog->len;
978         rprog.filter = (struct sock_filter *)(uintptr_t)filter_addr;
979         if (inj_poke(pid, prog_addr, &rprog, sizeof(rprog))) {
980                 ERROR("seccomp-inject: poke fprog: %m\n");
981                 return -1;
982         }
983 
984         if (inj_call_arm(pid, &saved, pc, thumb, SYS_prctl,
985                          PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0, &ret)) {
986                 ERROR("seccomp-inject: drive prctl: %m\n");
987                 goto restore;
988         }
989         if (ret) {
990                 ERROR("seccomp-inject: PR_SET_NO_NEW_PRIVS returned %ld\n", ret);
991                 goto restore;
992         }
993 
994         if (inj_call_arm(pid, &saved, pc, thumb, SYS_seccomp,
995                          SECCOMP_SET_MODE_FILTER, 0, (long)prog_addr, 0, 0, 0, &ret)) {
996                 ERROR("seccomp-inject: drive seccomp: %m\n");
997                 goto restore;
998         }
999         if (ret) {
1000                 ERROR("seccomp-inject: seccomp(SET_MODE_FILTER) returned %ld\n", ret);
1001                 goto restore;
1002         }
1003 
1004         if (inj_setregs(pid, &saved)) {
1005                 ERROR("seccomp-inject: restore SETREGSET: %m\n");
1006                 return -1;
1007         }
1008 
1009         return 0;
1010 
1011 restore:
1012         inj_setregs(pid, &saved);
1013         return -1;
1014 }
1015 #endif
1016 
1017 #if !defined(__arm__)
1018 static int run_to_addr(pid_t pid, unsigned long addr)
1019 {
1020         const unsigned char *bp = inj_bp_insn;
1021         size_t bplen = inj_bp_len();
1022         unsigned char saved[INJ_INSN_MAX];
1023         inj_regs regs;
1024         int status, sig = 0;
1025 
1026         if (inj_peek(pid, addr, saved, bplen)) {
1027                 ERROR("seccomp-inject: read bp target: %m\n");
1028                 return -1;
1029         }
1030         if (inj_poke(pid, addr, bp, bplen)) {
1031                 ERROR("seccomp-inject: poke breakpoint: %m\n");
1032                 return -1;
1033         }
1034 
1035         for (;;) {
1036                 if (ptrace(PTRACE_CONT, pid, 0, (void *)(long)sig)) {
1037                         ERROR("seccomp-inject: PTRACE_CONT to bp: %m\n");
1038                         goto restore;
1039                 }
1040                 if (waitpid(pid, &status, 0) < 0) {
1041                         ERROR("seccomp-inject: waitpid to bp: %m\n");
1042                         goto restore;
1043                 }
1044                 if (!WIFSTOPPED(status)) {
1045                         ERROR("seccomp-inject: workload exited before reaching target\n");
1046                         return -1;
1047                 }
1048                 if (WSTOPSIG(status) == SIGTRAP)
1049                         break;
1050                 sig = WSTOPSIG(status);
1051         }
1052 
1053         if (inj_getregs(pid, &regs)) {
1054                 ERROR("seccomp-inject: GETREGSET at bp: %m\n");
1055                 goto restore;
1056         }
1057         inj_set_pc(&regs, addr);
1058         if (inj_setregs(pid, &regs)) {
1059                 ERROR("seccomp-inject: SETREGSET at bp: %m\n");
1060                 goto restore;
1061         }
1062         inj_poke(pid, addr, saved, bplen);
1063 
1064         return 0;
1065 
1066 restore:
1067         inj_poke(pid, addr, saved, bplen);
1068         return -1;
1069 }
1070 #endif
1071 
1072 int seccomp_run_to_entry(pid_t pid)
1073 {
1074 #if defined(__arm__)
1075         return seccomp_run_to_entry_arm(pid);
1076 #else
1077         unsigned long entry;
1078 
1079         if (read_auxv(pid, AT_ENTRY, &entry)) {
1080                 ERROR("seccomp-inject: cannot read AT_ENTRY: %m\n");
1081                 return -1;
1082         }
1083 
1084         return run_to_addr(pid, entry);
1085 #endif
1086 }
1087 
1088 #if !defined(__arm__) && !defined(__i386__)
1089 static unsigned long find_libc_init(pid_t pid, int *main_argidx)
1090 {
1091         char path[64], line[600], rooted[PATH_MAX + 64], p[PATH_MAX];
1092         char seen[48][256];
1093         unsigned long bases[48];
1094         unsigned long lo, hi, val;
1095         int nseen = 0, i;
1096         FILE *f;
1097 
1098         *main_argidx = 0;
1099         snprintf(path, sizeof(path), "/proc/%d/maps", (int)pid);
1100         f = fopen(path, "r");
1101         if (!f)
1102                 return 0;
1103 
1104         while (fgets(line, sizeof(line), f)) {
1105                 if (sscanf(line, "%lx-%lx %*s %*s %*s %*s %4095s", &lo, &hi, p) < 3)
1106                         continue;
1107                 if (p[0] != '/')
1108                         continue;
1109                 for (i = 0; i < nseen; i++)
1110                         if (!strcmp(seen[i], p))
1111                                 break;
1112                 if (i < nseen || nseen >= 48)
1113                         continue;
1114                 strncpy(seen[nseen], p, sizeof(seen[0]) - 1);
1115                 seen[nseen][sizeof(seen[0]) - 1] = '\0';
1116                 bases[nseen] = lo;
1117                 nseen++;
1118         }
1119         fclose(f);
1120 
1121         for (i = 0; i < nseen; i++) {
1122                 snprintf(rooted, sizeof(rooted), "/proc/%d/root%s", (int)pid, seen[i]);
1123                 val = elf_dynsym_value(rooted, "__libc_start_main");
1124                 if (val) {
1125                         *main_argidx = 0;
1126                         return bases[i] + val;
1127                 }
1128         }
1129         for (i = 0; i < nseen; i++) {
1130                 snprintf(rooted, sizeof(rooted), "/proc/%d/root%s", (int)pid, seen[i]);
1131                 val = elf_dynsym_value(rooted, "__libc_init");
1132                 if (val) {
1133                         *main_argidx = 2;
1134                         return bases[i] + val;
1135                 }
1136         }
1137         return 0;
1138 }
1139 #endif
1140 
1141 int seccomp_marker_addrs(pid_t pid, unsigned long *at_entry, unsigned long *lsm, int *main_argidx)
1142 {
1143         *at_entry = 0;
1144         *lsm = 0;
1145         *main_argidx = 0;
1146 
1147         if (read_auxv(pid, AT_ENTRY, at_entry))
1148                 return -1;
1149 
1150 #if !defined(__arm__) && !defined(__i386__)
1151         *lsm = find_libc_init(pid, main_argidx);
1152 #endif
1153 
1154         return 0;
1155 }
1156 
1157 int seccomp_run_to_main(pid_t pid)
1158 {
1159 #if defined(__arm__)
1160         return seccomp_run_to_entry(pid);
1161 #else
1162         unsigned long at_entry, lsm, mainaddr;
1163         long nr, args[6];
1164         int main_argidx;
1165 
1166         if (seccomp_marker_addrs(pid, &at_entry, &lsm, &main_argidx))
1167                 return -1;
1168         if (!lsm)
1169                 return seccomp_run_to_entry(pid);
1170 
1171         if (run_to_addr(pid, lsm))
1172                 return -1;
1173         if (seccomp_read_syscall(pid, &nr, args))
1174                 return -1;
1175 
1176         mainaddr = (unsigned long)args[main_argidx];
1177         if (!mainaddr)
1178                 return -1;
1179 
1180         return run_to_addr(pid, mainaddr);
1181 #endif
1182 }
1183 
1184 int seccomp_run_to_main_from_entry(pid_t pid)
1185 {
1186 #if defined(__arm__)
1187         return 1;
1188 #else
1189         unsigned long at_entry, lsm, mainaddr;
1190         long nr, args[6];
1191         int main_argidx;
1192 
1193         if (seccomp_marker_addrs(pid, &at_entry, &lsm, &main_argidx))
1194                 return -1;
1195         if (!lsm)
1196                 return 1;
1197 
1198         if (run_to_addr(pid, lsm))
1199                 return -1;
1200         if (seccomp_read_syscall(pid, &nr, args))
1201                 return -1;
1202 
1203         mainaddr = (unsigned long)args[main_argidx];
1204         if (!mainaddr)
1205                 return -1;
1206 
1207         if (run_to_addr(pid, mainaddr))
1208                 return -1;
1209 
1210         return 0;
1211 #endif
1212 }
1213 
1214 int seccomp_bp_arm(pid_t pid, unsigned long addr, struct seccomp_bp *bp)
1215 {
1216 #if defined(__arm__)
1217         const unsigned char *ins;
1218         size_t len;
1219         int thumb;
1220 
1221         thumb = arm_thumb_at(addr);
1222         bp->addr = addr & ~1UL;
1223         ins = arm_bp_insn(thumb, &len);
1224 #else
1225         const unsigned char *ins = inj_bp_insn;
1226         size_t len = inj_bp_len();
1227 
1228         bp->addr = addr;
1229 #endif
1230 
1231         if (len > sizeof(bp->saved))
1232                 return -1;
1233         if (inj_peek(pid, bp->addr, bp->saved, len))
1234                 return -1;
1235         if (inj_poke(pid, bp->addr, ins, len))
1236                 return -1;
1237 
1238         bp->len = (unsigned char)len;
1239         bp->armed = 1;
1240 
1241         return 0;
1242 }
1243 
1244 int seccomp_bp_match(pid_t pid, struct seccomp_bp **bps, int n)
1245 {
1246         inj_regs regs;
1247         unsigned long pc;
1248         int i;
1249 
1250         if (inj_getregs(pid, &regs))
1251                 return -1;
1252 
1253         pc = inj_pc(&regs);
1254 #if defined(__arm__)
1255         pc &= ~1UL;
1256 #endif
1257 
1258         for (i = 0; i < n; i++) {
1259                 if (!bps[i] || !bps[i]->armed)
1260                         continue;
1261                 if (pc != bps[i]->addr && pc != bps[i]->addr + bps[i]->len)
1262                         continue;
1263 
1264                 inj_poke(pid, bps[i]->addr, bps[i]->saved, bps[i]->len);
1265                 inj_set_pc(&regs, bps[i]->addr);
1266                 if (inj_setregs(pid, &regs))
1267                         return -1;
1268                 bps[i]->armed = 0;
1269 
1270                 return i;
1271         }
1272 
1273         return -1;
1274 }
1275 
1276 int seccomp_force_errno(pid_t pid, int err)
1277 {
1278 #if defined(__aarch64__)
1279         inj_regs regs;
1280         int scno = -1;
1281         struct iovec iov;
1282 
1283         iov.iov_base = &scno;
1284         iov.iov_len = sizeof(scno);
1285         if (ptrace(PTRACE_SETREGSET, pid, (void *)NT_ARM_SYSTEM_CALL, &iov))
1286                 return -1;
1287         if (inj_getregs(pid, &regs))
1288                 return -1;
1289         regs.regs[0] = (unsigned long long)(long long)-err;
1290         if (inj_setregs(pid, &regs))
1291                 return -1;
1292 
1293         return 0;
1294 #elif defined(__arm__)
1295         inj_regs regs;
1296 
1297         if (ptrace(PTRACE_SET_SYSCALL, pid, 0, (void *)-1L))
1298                 return -1;
1299         if (inj_getregs(pid, &regs))
1300                 return -1;
1301         regs.uregs[0] = (unsigned long)(long)-err;
1302         if (inj_setregs(pid, &regs))
1303                 return -1;
1304 
1305         return 0;
1306 #elif defined(__mips__)
1307         inj_regs regs;
1308 
1309         if (inj_getregs(pid, &regs))
1310                 return -1;
1311         regs.gregs[MIPS_EF_V0] = (unsigned long)(long)-1;
1312         if (inj_setregs(pid, &regs))
1313                 return -1;
1314 
1315         return 1;
1316 #elif defined(__x86_64__) || defined(__i386__) || \
1317       (defined(__riscv) && __riscv_xlen == 64) || \
1318       (defined(__loongarch__) && __loongarch_grlen == 64) || \
1319       defined(__powerpc64__) || defined(__powerpc__)
1320         inj_regs regs;
1321 
1322         if (inj_getregs(pid, &regs))
1323                 return -1;
1324 
1325 #if defined(__x86_64__)
1326         regs.orig_rax = (unsigned long)-1;
1327         regs.rax = (unsigned long)(long)-err;
1328 #elif defined(__i386__)
1329         regs.orig_eax = (unsigned long)-1;
1330         regs.eax = (unsigned long)(long)-err;
1331 #elif defined(__riscv) && __riscv_xlen == 64
1332         regs.a7 = (unsigned long)-1;
1333         regs.a0 = (unsigned long)(long)-err;
1334 #elif defined(__loongarch__) && __loongarch_grlen == 64
1335         regs.regs[11] = (unsigned long)-1;
1336         regs.regs[4] = (unsigned long)(long)-err;
1337 #else
1338         regs.gpr[0] = (unsigned long)-1;
1339         regs.gpr[3] = (unsigned long)err;
1340         regs.ccr |= 0x10000000UL;
1341 #endif
1342 
1343         if (inj_setregs(pid, &regs))
1344                 return -1;
1345 
1346         return 0;
1347 #else
1348         (void)pid;
1349         (void)err;
1350         return -1;
1351 #endif
1352 }
1353 
1354 int seccomp_force_errno_exit(pid_t pid, int err)
1355 {
1356 #if defined(__mips__)
1357         inj_regs regs;
1358 
1359         if (inj_getregs(pid, &regs))
1360                 return -1;
1361 
1362         regs.gregs[MIPS_EF_V0] = (unsigned long)(long)err;
1363         regs.gregs[MIPS_EF_A3] = 1;
1364 
1365         if (inj_setregs(pid, &regs))
1366                 return -1;
1367 
1368         return 0;
1369 #else
1370         (void)pid;
1371         (void)err;
1372         return -1;
1373 #endif
1374 }
1375 
1376 int seccomp_inject(pid_t pid, struct sock_fprog *prog)
1377 {
1378 #if defined(__arm__)
1379         return seccomp_inject_arm(pid, prog);
1380 #else
1381         inj_regs saved;
1382         struct sock_fprog rprog;
1383         unsigned char savedinsn[INJ_INSN_MAX];
1384         unsigned long sp, pc, filter_addr, prog_addr;
1385         size_t filterlen;
1386         long ret;
1387 
1388         if (inj_getregs(pid, &saved)) {
1389                 ERROR("seccomp-inject: GETREGSET: %m\n");
1390                 return -1;
1391         }
1392 
1393         pc = inj_pc(&saved);
1394         sp = inj_sp(&saved);
1395         filterlen = (size_t)prog->len * sizeof(struct sock_filter);
1396 
1397         filter_addr = (sp - 4096 - filterlen - sizeof(rprog)) & ~0xfUL;
1398         prog_addr = (filter_addr + filterlen + 0xf) & ~0xfUL;
1399 
1400         if (inj_peek(pid, pc, savedinsn, inj_syscall_len())) {
1401                 ERROR("seccomp-inject: read pc: %m\n");
1402                 return -1;
1403         }
1404         if (inj_poke(pid, pc, inj_syscall_insn, inj_syscall_len())) {
1405                 ERROR("seccomp-inject: poke trap: %m\n");
1406                 return -1;
1407         }
1408         if (inj_poke(pid, filter_addr, prog->filter, filterlen)) {
1409                 ERROR("seccomp-inject: poke filter: %m\n");
1410                 goto restore;
1411         }
1412 
1413         rprog.len = prog->len;
1414         rprog.filter = (struct sock_filter *)(uintptr_t)filter_addr;
1415         if (inj_poke(pid, prog_addr, &rprog, sizeof(rprog))) {
1416                 ERROR("seccomp-inject: poke fprog: %m\n");
1417                 goto restore;
1418         }
1419 
1420         if (inj_call(pid, &saved, pc, SYS_prctl,
1421                      PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0, 0, &ret)) {
1422                 ERROR("seccomp-inject: drive prctl: %m\n");
1423                 goto restore;
1424         }
1425         if (ret) {
1426                 ERROR("seccomp-inject: PR_SET_NO_NEW_PRIVS returned %ld\n", ret);
1427                 goto restore;
1428         }
1429 
1430         if (inj_call(pid, &saved, pc, SYS_seccomp,
1431                      SECCOMP_SET_MODE_FILTER, 0, (long)prog_addr, 0, 0, 0, &ret)) {
1432                 ERROR("seccomp-inject: drive seccomp: %m\n");
1433                 goto restore;
1434         }
1435         if (ret) {
1436                 ERROR("seccomp-inject: seccomp(SET_MODE_FILTER) returned %ld\n", ret);
1437                 goto restore;
1438         }
1439 
1440         inj_poke(pid, pc, savedinsn, inj_syscall_len());
1441         inj_clear_restart(&saved);
1442         if (inj_setregs(pid, &saved)) {
1443                 ERROR("seccomp-inject: restore SETREGSET: %m\n");
1444                 return -1;
1445         }
1446 
1447         return 0;
1448 
1449 restore:
1450         inj_poke(pid, pc, savedinsn, inj_syscall_len());
1451         inj_clear_restart(&saved);
1452         inj_setregs(pid, &saved);
1453 
1454         return -1;
1455 #endif
1456 }
1457 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt