forked from romab/perl-Linux-Seccomp_bpf
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSeccomp_bpf.xs
More file actions
104 lines (92 loc) · 2.65 KB
/
Copy pathSeccomp_bpf.xs
File metadata and controls
104 lines (92 loc) · 2.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
MODULE = Linux::Seccomp_bpf PACKAGE = Linux::Seccomp_bpf
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/prctl.h>
#include <linux/seccomp.h>
#include <seccomp.h>
int
scmp_bpf_is_available()
CODE:
int r;
r = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
if (r < 0) {
RETVAL=0;
switch (errno) {
case ENOSYS:
fprintf(stderr, "seccomp not available: Needs at least kernel 2.6.23\n");
break;
case EINVAL:
fprintf(stderr, "SECCOMP_FILTER is not available.\nYour kernel needs\n\
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y\nCONFIG_SECCOMP_FILTER=y\nCONFIG_SECCOMP=y\n");
break;
default:
fprintf(stderr, "unknown PR_GET_SECCOMP error: %s\n",
strerror(errno));
}
}
else {
RETVAL=1;
}
OUTPUT:
RETVAL
void
inl_scmp_bpf_install_filter(SV* syscalls)
INIT:
I32 last_num_call_idx = 0;
SvGETMAGIC(syscalls);
if ((!SvROK(syscalls)) || (SvTYPE(SvRV(syscalls)) != SVt_PVAV)
|| ((last_num_call_idx = av_len((AV *)SvRV(syscalls))) < 0))
{
XSRETURN_UNDEF;
}
CODE:
scmp_filter_ctx ctx;
int i;
int r;
r = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
if (r < 0) {
perror("failed to set PR_ST_NO_NEW_PRIVS:");
exit(errno);
}
// libseccomp initialization
ctx = seccomp_init(SCMP_ACT_KILL);
if (ctx == NULL) {
fprintf(stderr, "seccomp_init failed\n");
exit(-1);
}
for (i = 0; i <= last_num_call_idx ; i++) {
STRLEN l;
char *h = SvPV(*av_fetch((AV *)SvRV(syscalls), i, 0), l);
// We do not want to use atoi(), why does linux not have strtonum :(
char *ep;
errno = 0;
unsigned long num = strtoul(h, &ep, 10);
if (h[0] == '\0' || *ep != '\0') {
fprintf(stderr, "syscall not a number: %s\n", h);
exit(-2);
}
if (errno == ERANGE && num == ULONG_MAX) {
fprintf(stderr, "syscall out of unsigned long range: %s\n", h);
exit(-3);
}
if (num > 2048) {
fprintf(stderr, "syscall number not sane: %s\n", h);
exit(-3);
}
r = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, num, 0);
if (r < 0) {
fprintf(stderr, "Failed to add syscall %d\n", r);
}
}
r = seccomp_load(ctx);
if (r != 0) {
fprintf(stderr, "seccomp_load failed with exit code %d\n", r);
exit(r);
}
seccomp_release(ctx);