summaryrefslogtreecommitdiff
path: root/sys_linux.c
diff options
context:
space:
mode:
authorVincent Blut <vincent.debian@free.fr>2020-10-07 19:12:27 +0200
committerVincent Blut <vincent.debian@free.fr>2020-10-07 19:12:27 +0200
commit053197ae1524b74d40c3d19bad3e137146c1ddd6 (patch)
tree829cb7231c945c8e1e7d8ad62e94c4cb0f902ec6 /sys_linux.c
parent97a44a68befd56dbaa6540e5b25b04e6d6fbad06 (diff)
New upstream version 4.0
Diffstat (limited to 'sys_linux.c')
-rw-r--r--sys_linux.c231
1 files changed, 168 insertions, 63 deletions
diff --git a/sys_linux.c b/sys_linux.c
index 898dc7a..0b24445 100644
--- a/sys_linux.c
+++ b/sys_linux.c
@@ -426,7 +426,7 @@ SYS_Linux_Finalise(void)
#ifdef FEAT_PRIVDROP
void
-SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
+SYS_Linux_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control)
{
char cap_text[256];
cap_t cap;
@@ -437,13 +437,23 @@ SYS_Linux_DropRoot(uid_t uid, gid_t gid, int clock_control)
UTI_DropRoot(uid, gid);
- /* Keep CAP_NET_BIND_SERVICE only if a server NTP port can be opened
- and keep CAP_SYS_TIME only if the clock control is enabled */
- if (snprintf(cap_text, sizeof (cap_text), "%s %s",
- CNF_GetNTPPort() ? "cap_net_bind_service=ep" : "",
+ /* Keep CAP_NET_BIND_SERVICE if the NTP server sockets may need to be bound
+ to a privileged port.
+ Keep CAP_NET_RAW if an NTP socket may need to be bound to a device on
+ kernels before 5.7.
+ Keep CAP_SYS_TIME if the clock control is enabled. */
+ if (snprintf(cap_text, sizeof (cap_text), "%s %s %s",
+ (CNF_GetNTPPort() > 0 && CNF_GetNTPPort() < 1024) ?
+ "cap_net_bind_service=ep" : "",
+ (CNF_GetBindNtpInterface() || CNF_GetBindAcquisitionInterface()) &&
+ !SYS_Linux_CheckKernelVersion(5, 7) ? "cap_net_raw=ep" : "",
clock_control ? "cap_sys_time=ep" : "") >= sizeof (cap_text))
assert(0);
+ /* Helpers don't need any capabilities */
+ if (context != SYS_MAIN_PROCESS)
+ cap_text[0] = '\0';
+
if ((cap = cap_from_text(cap_text)) == NULL) {
LOG_FATAL("cap_from_text() failed");
}
@@ -474,39 +484,127 @@ void check_seccomp_applicability(void)
/* ================================================== */
void
-SYS_Linux_EnableSystemCallFilter(int level)
+SYS_Linux_EnableSystemCallFilter(int level, SYS_ProcessContext context)
{
const int syscalls[] = {
/* Clock */
- SCMP_SYS(adjtimex), SCMP_SYS(clock_gettime), SCMP_SYS(gettimeofday),
- SCMP_SYS(settimeofday), SCMP_SYS(time),
+ SCMP_SYS(adjtimex),
+ SCMP_SYS(clock_adjtime),
+#ifdef __NR_clock_adjtime64
+ SCMP_SYS(clock_adjtime64),
+#endif
+ SCMP_SYS(clock_gettime),
+#ifdef __NR_clock_gettime64
+ SCMP_SYS(clock_gettime64),
+#endif
+ SCMP_SYS(gettimeofday),
+ SCMP_SYS(settimeofday),
+ SCMP_SYS(time),
+
/* Process */
- SCMP_SYS(clone), SCMP_SYS(exit), SCMP_SYS(exit_group), SCMP_SYS(getpid),
- SCMP_SYS(getrlimit), SCMP_SYS(rt_sigaction), SCMP_SYS(rt_sigreturn),
- SCMP_SYS(rt_sigprocmask), SCMP_SYS(set_tid_address), SCMP_SYS(sigreturn),
- SCMP_SYS(wait4), SCMP_SYS(waitpid),
+ SCMP_SYS(clone),
+ SCMP_SYS(exit),
+ SCMP_SYS(exit_group),
+ SCMP_SYS(getpid),
+ SCMP_SYS(getrlimit),
+ SCMP_SYS(getuid),
+ SCMP_SYS(rt_sigaction),
+ SCMP_SYS(rt_sigreturn),
+ SCMP_SYS(rt_sigprocmask),
+ SCMP_SYS(set_tid_address),
+ SCMP_SYS(sigreturn),
+ SCMP_SYS(wait4),
+ SCMP_SYS(waitpid),
+
/* Memory */
- SCMP_SYS(brk), SCMP_SYS(madvise), SCMP_SYS(mmap), SCMP_SYS(mmap2),
- SCMP_SYS(mprotect), SCMP_SYS(mremap), SCMP_SYS(munmap), SCMP_SYS(shmdt),
+ SCMP_SYS(brk),
+ SCMP_SYS(madvise),
+ SCMP_SYS(mmap),
+ SCMP_SYS(mmap2),
+ SCMP_SYS(mprotect),
+ SCMP_SYS(mremap),
+ SCMP_SYS(munmap),
+ SCMP_SYS(shmdt),
+
/* Filesystem */
- SCMP_SYS(_llseek), SCMP_SYS(access), SCMP_SYS(chmod), SCMP_SYS(chown),
- SCMP_SYS(chown32), SCMP_SYS(faccessat), SCMP_SYS(fchmodat), SCMP_SYS(fchownat),
- SCMP_SYS(fstat), SCMP_SYS(fstat64), SCMP_SYS(getdents), SCMP_SYS(getdents64),
- SCMP_SYS(lseek), SCMP_SYS(newfstatat), SCMP_SYS(rename), SCMP_SYS(renameat),
- SCMP_SYS(stat), SCMP_SYS(stat64), SCMP_SYS(statfs), SCMP_SYS(statfs64),
- SCMP_SYS(unlink), SCMP_SYS(unlinkat),
+ SCMP_SYS(_llseek),
+ SCMP_SYS(access),
+ SCMP_SYS(chmod),
+ SCMP_SYS(chown),
+ SCMP_SYS(chown32),
+ SCMP_SYS(faccessat),
+ SCMP_SYS(fchmodat),
+ SCMP_SYS(fchownat),
+ SCMP_SYS(fstat),
+ SCMP_SYS(fstat64),
+ SCMP_SYS(getdents),
+ SCMP_SYS(getdents64),
+ SCMP_SYS(lseek),
+ SCMP_SYS(lstat),
+ SCMP_SYS(lstat64),
+ SCMP_SYS(newfstatat),
+ SCMP_SYS(readlink),
+ SCMP_SYS(readlinkat),
+ SCMP_SYS(rename),
+ SCMP_SYS(renameat),
+ SCMP_SYS(renameat2),
+ SCMP_SYS(stat),
+ SCMP_SYS(stat64),
+ SCMP_SYS(statfs),
+ SCMP_SYS(statfs64),
+ SCMP_SYS(unlink),
+ SCMP_SYS(unlinkat),
+
/* Socket */
- SCMP_SYS(bind), SCMP_SYS(connect), SCMP_SYS(getsockname), SCMP_SYS(getsockopt),
- SCMP_SYS(recv), SCMP_SYS(recvfrom), SCMP_SYS(recvmmsg), SCMP_SYS(recvmsg),
- SCMP_SYS(send), SCMP_SYS(sendmmsg), SCMP_SYS(sendmsg), SCMP_SYS(sendto),
+ SCMP_SYS(accept),
+ SCMP_SYS(bind),
+ SCMP_SYS(connect),
+ SCMP_SYS(getsockname),
+ SCMP_SYS(getsockopt),
+ SCMP_SYS(recv),
+ SCMP_SYS(recvfrom),
+ SCMP_SYS(recvmmsg),
+#ifdef __NR_recvmmsg_time64
+ SCMP_SYS(recvmmsg_time64),
+#endif
+ SCMP_SYS(recvmsg),
+ SCMP_SYS(send),
+ SCMP_SYS(sendmmsg),
+ SCMP_SYS(sendmsg),
+ SCMP_SYS(sendto),
+ SCMP_SYS(shutdown),
/* TODO: check socketcall arguments */
SCMP_SYS(socketcall),
+
/* General I/O */
- SCMP_SYS(_newselect), SCMP_SYS(close), SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(pipe),
- SCMP_SYS(pipe2), SCMP_SYS(poll), SCMP_SYS(ppoll), SCMP_SYS(pselect6), SCMP_SYS(read),
- SCMP_SYS(futex), SCMP_SYS(select), SCMP_SYS(set_robust_list), SCMP_SYS(write),
+ SCMP_SYS(_newselect),
+ SCMP_SYS(close),
+ SCMP_SYS(open),
+ SCMP_SYS(openat),
+ SCMP_SYS(pipe),
+ SCMP_SYS(pipe2),
+ SCMP_SYS(poll),
+ SCMP_SYS(ppoll),
+#ifdef __NR_ppoll_time64
+ SCMP_SYS(ppoll_time64),
+#endif
+ SCMP_SYS(pselect6),
+#ifdef __NR_pselect6_time64
+ SCMP_SYS(pselect6_time64),
+#endif
+ SCMP_SYS(read),
+ SCMP_SYS(futex),
+#ifdef __NR_futex_time64
+ SCMP_SYS(futex_time64),
+#endif
+ SCMP_SYS(select),
+ SCMP_SYS(set_robust_list),
+ SCMP_SYS(write),
+
/* Miscellaneous */
- SCMP_SYS(getrandom), SCMP_SYS(sysinfo), SCMP_SYS(uname),
+ SCMP_SYS(getrandom),
+ SCMP_SYS(sysinfo),
+ SCMP_SYS(uname),
};
const int socket_domains[] = {
@@ -522,13 +620,16 @@ SYS_Linux_EnableSystemCallFilter(int level)
{ SOL_IPV6, IPV6_V6ONLY }, { SOL_IPV6, IPV6_RECVPKTINFO },
#endif
{ SOL_SOCKET, SO_BROADCAST }, { SOL_SOCKET, SO_REUSEADDR },
+#ifdef SO_REUSEPORT
+ { SOL_SOCKET, SO_REUSEPORT },
+#endif
{ SOL_SOCKET, SO_TIMESTAMP }, { SOL_SOCKET, SO_TIMESTAMPNS },
#ifdef HAVE_LINUX_TIMESTAMPING
{ SOL_SOCKET, SO_SELECT_ERR_QUEUE }, { SOL_SOCKET, SO_TIMESTAMPING },
#endif
};
- const static int fcntls[] = { F_GETFD, F_SETFD, F_SETFL };
+ const static int fcntls[] = { F_GETFD, F_SETFD, F_GETFL, F_SETFL };
const static unsigned long ioctls[] = {
FIONREAD, TCGETS,
@@ -558,14 +659,16 @@ SYS_Linux_EnableSystemCallFilter(int level)
scmp_filter_ctx *ctx;
int i;
- /* Check if the chronyd configuration is supported */
- check_seccomp_applicability();
+ if (context == SYS_MAIN_PROCESS) {
+ /* Check if the chronyd configuration is supported */
+ check_seccomp_applicability();
- /* Start the helper process, which will run without any seccomp filter. It
- will be used for getaddrinfo(), for which it's difficult to maintain a
- list of required system calls (with glibc it depends on what NSS modules
- are installed and enabled on the system). */
- PRV_StartHelper();
+ /* Start the helper process, which will run without any seccomp filter. It
+ will be used for getaddrinfo(), for which it's difficult to maintain a
+ list of required system calls (with glibc it depends on what NSS modules
+ are installed and enabled on the system). */
+ PRV_StartHelper();
+ }
ctx = seccomp_init(level > 0 ? SCMP_ACT_KILL : SCMP_ACT_TRAP);
if (ctx == NULL)
@@ -577,42 +680,44 @@ SYS_Linux_EnableSystemCallFilter(int level)
goto add_failed;
}
- /* Allow sockets to be created only in selected domains */
- for (i = 0; i < sizeof (socket_domains) / sizeof (*socket_domains); i++) {
- if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
- SCMP_A0(SCMP_CMP_EQ, socket_domains[i])) < 0)
- goto add_failed;
- }
+ if (context == SYS_MAIN_PROCESS) {
+ /* Allow opening sockets in selected domains */
+ for (i = 0; i < sizeof (socket_domains) / sizeof (*socket_domains); i++) {
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1,
+ SCMP_A0(SCMP_CMP_EQ, socket_domains[i])) < 0)
+ goto add_failed;
+ }
- /* Allow setting only selected sockets options */
- for (i = 0; i < sizeof (socket_options) / sizeof (*socket_options); i++) {
- if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 3,
- SCMP_A1(SCMP_CMP_EQ, socket_options[i][0]),
- SCMP_A2(SCMP_CMP_EQ, socket_options[i][1]),
- SCMP_A4(SCMP_CMP_LE, sizeof (int))) < 0)
- goto add_failed;
- }
+ /* Allow selected socket options */
+ for (i = 0; i < sizeof (socket_options) / sizeof (*socket_options); i++) {
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt), 3,
+ SCMP_A1(SCMP_CMP_EQ, socket_options[i][0]),
+ SCMP_A2(SCMP_CMP_EQ, socket_options[i][1]),
+ SCMP_A4(SCMP_CMP_LE, sizeof (int))) < 0)
+ goto add_failed;
+ }
- /* Allow only selected fcntl calls */
- for (i = 0; i < sizeof (fcntls) / sizeof (*fcntls); i++) {
- if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1,
- SCMP_A1(SCMP_CMP_EQ, fcntls[i])) < 0 ||
- seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1,
- SCMP_A1(SCMP_CMP_EQ, fcntls[i])) < 0)
- goto add_failed;
- }
+ /* Allow selected fcntl calls */
+ for (i = 0; i < sizeof (fcntls) / sizeof (*fcntls); i++) {
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 1,
+ SCMP_A1(SCMP_CMP_EQ, fcntls[i])) < 0 ||
+ seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 1,
+ SCMP_A1(SCMP_CMP_EQ, fcntls[i])) < 0)
+ goto add_failed;
+ }
- /* Allow only selected ioctls */
- for (i = 0; i < sizeof (ioctls) / sizeof (*ioctls); i++) {
- if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1,
- SCMP_A1(SCMP_CMP_EQ, ioctls[i])) < 0)
- goto add_failed;
+ /* Allow selected ioctls */
+ for (i = 0; i < sizeof (ioctls) / sizeof (*ioctls); i++) {
+ if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1,
+ SCMP_A1(SCMP_CMP_EQ, ioctls[i])) < 0)
+ goto add_failed;
+ }
}
if (seccomp_load(ctx) < 0)
LOG_FATAL("Failed to load seccomp rules");
- LOG(LOGS_INFO, "Loaded seccomp filter");
+ LOG(context == SYS_MAIN_PROCESS ? LOGS_INFO : LOGS_DEBUG, "Loaded seccomp filter");
seccomp_release(ctx);
return;