summaryrefslogtreecommitdiff
path: root/methods
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2017-10-22 23:34:03 +0200
committerJulian Andres Klode <jak@debian.org>2017-10-22 23:38:31 +0200
commit32bcbd73e0988d2d2237690ffae33b4f5cc5ff81 (patch)
tree3234d16c59f85a84a02371e6ef2f0bc79af42738 /methods
parent9130b5f9304b7f58273a826ff9acf04e10c6f98e (diff)
Sandbox methods with seccomp-BPF; except cdrom, gpgv, rsh
This reduces the number of syscalls to about 140 from about 350 or so, significantly reducing security risks. Also change prepare-release to ignore the architecture lists in the build dependencies when generating the build-depends package for travis. We might want to clean up things a bit more and/or move it somewhere else.
Diffstat (limited to 'methods')
-rw-r--r--methods/CMakeLists.txt22
-rw-r--r--methods/aptmethod.h217
-rw-r--r--methods/copy.cc6
-rw-r--r--methods/file.cc5
-rw-r--r--methods/ftp.cc1
-rw-r--r--methods/http.cc2
-rw-r--r--methods/rred.cc5
-rw-r--r--methods/store.cc1
8 files changed, 240 insertions, 19 deletions
diff --git a/methods/CMakeLists.txt b/methods/CMakeLists.txt
index 72f07e87e..60c636c7b 100644
--- a/methods/CMakeLists.txt
+++ b/methods/CMakeLists.txt
@@ -1,4 +1,6 @@
# Create the executable targets
+include_directories($<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_INCLUDE_DIR}>)
+
add_executable(file file.cc)
add_executable(copy copy.cc)
add_executable(store store.cc)
@@ -14,16 +16,16 @@ target_compile_definitions(http PRIVATE ${GNUTLS_DEFINITIONS})
target_include_directories(http PRIVATE ${GNUTLS_INCLUDE_DIR})
# Link the executables against the libraries
-target_link_libraries(file apt-pkg)
-target_link_libraries(copy apt-pkg)
-target_link_libraries(store apt-pkg)
-target_link_libraries(gpgv apt-pkg)
-target_link_libraries(cdrom apt-pkg)
-target_link_libraries(http apt-pkg ${GNUTLS_LIBRARIES})
-target_link_libraries(mirror apt-pkg ${RESOLV_LIBRARIES} ${GNUTLS_LIBRARIES})
-target_link_libraries(ftp apt-pkg ${GNUTLS_LIBRARIES})
-target_link_libraries(rred apt-pkg)
-target_link_libraries(rsh apt-pkg)
+target_link_libraries(file apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(copy apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(store apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(gpgv apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(cdrom apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(http apt-pkg ${GNUTLS_LIBRARIES} $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(mirror apt-pkg ${RESOLV_LIBRARIES} ${GNUTLS_LIBRARIES} $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(ftp apt-pkg ${GNUTLS_LIBRARIES} $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(rred apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
+target_link_libraries(rsh apt-pkg $<$<BOOL:${SECCOMP_FOUND}>:${SECCOMP_LIBRARIES}>)
# Install the library
install(TARGETS file copy store gpgv cdrom http ftp rred rsh mirror
diff --git a/methods/aptmethod.h b/methods/aptmethod.h
index 23fd036dd..d5d426914 100644
--- a/methods/aptmethod.h
+++ b/methods/aptmethod.h
@@ -1,6 +1,8 @@
#ifndef APT_APTMETHOD_H
#define APT_APTMETHOD_H
+#include "config.h"
+
#include <apt-pkg/acquire-method.h>
#include <apt-pkg/configuration.h>
#include <apt-pkg/error.h>
@@ -19,6 +21,10 @@
#include <apti18n.h>
+#ifdef HAVE_SECCOMP
+#include <seccomp.h>
+#endif
+
static bool hasDoubleColon(std::string const &n)
{
return n.find("::") != std::string::npos;
@@ -28,8 +34,15 @@ class aptMethod : public pkgAcqMethod
{
protected:
std::string const Binary;
+ unsigned long SeccompFlags;
+ enum Seccomp
+ {
+ BASE = (1 << 1),
+ NETWORK = (1 << 2),
+ DIRECTORY = (1 << 3),
+ };
-public:
+ public:
virtual bool Configuration(std::string Message) APT_OVERRIDE
{
if (pkgAcqMethod::Configuration(Message) == false)
@@ -39,7 +52,198 @@ public:
_config->MoveSubTree(conf.c_str(), NULL);
DropPrivsOrDie();
+ if (LoadSeccomp() == false)
+ return false;
+
+ return true;
+ }
+
+ bool LoadSeccomp()
+ {
+#ifdef HAVE_SECCOMP
+ int rc;
+ scmp_filter_ctx ctx = NULL;
+
+ if (SeccompFlags == 0)
+ return true;
+
+ if (_config->FindB("APT::Sandbox::Seccomp", true) == false)
+ return true;
+
+ ctx = seccomp_init(SCMP_ACT_TRAP);
+ if (ctx == NULL)
+ return _error->FatalE("HttpMethod::Configuration", "Cannot init seccomp");
+
+#define ALLOW(what) \
+ if ((rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(what), 0))) \
+ return _error->FatalE("HttpMethod::Configuration", "Cannot allow %s: %s", #what, strerror(-rc));
+ for (auto &custom : _config->FindVector("APT::Sandbox::Seccomp::Trap"))
+ {
+ if ((rc = seccomp_rule_add(ctx, SCMP_ACT_TRAP, seccomp_syscall_resolve_name(custom.c_str()), 0)))
+ return _error->FatalE("HttpMethod::Configuration", "Cannot trap %s: %s", custom.c_str(), strerror(-rc));
+ }
+
+ ALLOW(access);
+ ALLOW(arch_prctl);
+ ALLOW(brk);
+ ALLOW(chmod);
+ ALLOW(chown);
+ ALLOW(chown32);
+ ALLOW(clock_getres);
+ ALLOW(clock_gettime);
+ ALLOW(close);
+ ALLOW(creat);
+ ALLOW(dup);
+ ALLOW(dup2);
+ ALLOW(dup3);
+ ALLOW(exit);
+ ALLOW(exit_group);
+ ALLOW(faccessat);
+ ALLOW(fchmod);
+ ALLOW(fchmodat);
+ ALLOW(fchown);
+ ALLOW(fchown32);
+ ALLOW(fchownat);
+ ALLOW(fcntl);
+ ALLOW(fcntl64);
+ ALLOW(fdatasync);
+ ALLOW(flock);
+ ALLOW(fstat);
+ ALLOW(fstat64);
+ ALLOW(fstatat64);
+ ALLOW(fstatfs);
+ ALLOW(fstatfs64);
+ ALLOW(fsync);
+ ALLOW(ftime);
+ ALLOW(ftruncate);
+ ALLOW(ftruncate64);
+ ALLOW(futex);
+ ALLOW(futimesat);
+ ALLOW(getegid);
+ ALLOW(getegid32);
+ ALLOW(geteuid);
+ ALLOW(geteuid32);
+ ALLOW(getgid);
+ ALLOW(getgid32);
+ ALLOW(getgroups);
+ ALLOW(getgroups32);
+ ALLOW(getpeername);
+ ALLOW(getpgid);
+ ALLOW(getpgrp);
+ ALLOW(getpid);
+ ALLOW(getppid);
+ ALLOW(getrandom);
+ ALLOW(getresgid);
+ ALLOW(getresgid32);
+ ALLOW(getresuid);
+ ALLOW(getresuid32);
+ ALLOW(getrlimit);
+ ALLOW(get_robust_list);
+ ALLOW(getrusage);
+ ALLOW(gettid);
+ ALLOW(gettimeofday);
+ ALLOW(getuid);
+ ALLOW(getuid32);
+ ALLOW(ioctl);
+ ALLOW(lchown);
+ ALLOW(lchown32);
+ ALLOW(_llseek);
+ ALLOW(lseek);
+ ALLOW(lstat);
+ ALLOW(lstat64);
+ ALLOW(madvise);
+ ALLOW(mmap);
+ ALLOW(mmap2);
+ ALLOW(mprotect);
+ ALLOW(mremap);
+ ALLOW(msync);
+ ALLOW(munmap);
+ ALLOW(newfstatat);
+ ALLOW(oldfstat);
+ ALLOW(oldlstat);
+ ALLOW(oldolduname);
+ ALLOW(oldstat);
+ ALLOW(olduname);
+ ALLOW(open);
+ ALLOW(openat);
+ ALLOW(pipe);
+ ALLOW(pipe2);
+ ALLOW(poll);
+ ALLOW(ppoll);
+ ALLOW(prctl);
+ ALLOW(prlimit64);
+ ALLOW(pselect6);
+ ALLOW(read);
+ ALLOW(rename);
+ ALLOW(renameat);
+ ALLOW(rt_sigaction);
+ ALLOW(rt_sigpending);
+ ALLOW(rt_sigprocmask);
+ ALLOW(rt_sigqueueinfo);
+ ALLOW(rt_sigreturn);
+ ALLOW(rt_sigsuspend);
+ ALLOW(rt_sigtimedwait);
+ ALLOW(sched_yield);
+ ALLOW(select);
+ ALLOW(set_robust_list);
+ ALLOW(sigaction);
+ ALLOW(sigpending);
+ ALLOW(sigprocmask);
+ ALLOW(sigreturn);
+ ALLOW(sigsuspend);
+ ALLOW(stat);
+ ALLOW(statfs);
+ ALLOW(sync);
+ ALLOW(syscall);
+ ALLOW(time);
+ ALLOW(truncate);
+ ALLOW(truncate64);
+ ALLOW(ugetrlimit);
+ ALLOW(umask);
+ ALLOW(uname);
+ ALLOW(unlink);
+ ALLOW(unlinkat);
+ ALLOW(utime);
+ ALLOW(utimensat);
+ ALLOW(utimes);
+ ALLOW(write);
+
+ if ((SeccompFlags & Seccomp::NETWORK) != 0)
+ {
+ ALLOW(bind);
+ ALLOW(connect);
+ ALLOW(getsockname);
+ ALLOW(getsockopt);
+ ALLOW(recv);
+ ALLOW(recvfrom);
+ ALLOW(recvmsg);
+ ALLOW(send);
+ ALLOW(sendmsg);
+ ALLOW(sendto);
+ ALLOW(setsockopt);
+ ALLOW(socket);
+ }
+
+ if ((SeccompFlags & Seccomp::DIRECTORY) != 0)
+ {
+ ALLOW(readdir);
+ ALLOW(getdents);
+ ALLOW(getdents64);
+ }
+
+ for (auto &custom : _config->FindVector("APT::Sandbox::Seccomp::Allow"))
+ {
+ if ((rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_syscall_resolve_name(custom.c_str()), 0)))
+ return _error->FatalE("HttpMethod::Configuration", "Cannot allow %s: %s", custom.c_str(), strerror(-rc));
+ }
+
+#undef ALLOW
+
+ rc = seccomp_load(ctx);
+ if (rc != 0)
+ return _error->FatalE("HttpMethod::Configuration", "could not load seccomp policy: %s", strerror(-rc));
+#endif
return true;
}
@@ -139,8 +343,8 @@ public:
return true;
}
- aptMethod(std::string &&Binary, char const * const Ver, unsigned long const Flags) APT_NONNULL(3) :
- pkgAcqMethod(Ver, Flags), Binary(Binary), methodNames({Binary})
+ aptMethod(std::string &&Binary, char const *const Ver, unsigned long const Flags) APT_NONNULL(3)
+ : pkgAcqMethod(Ver, Flags), Binary(Binary), SeccompFlags(0), methodNames({Binary})
{
try {
std::locale::global(std::locale(""));
@@ -172,6 +376,9 @@ public:
DropPrivsOrDie();
+ if (LoadSeccomp() == false)
+ return false;
+
return true;
}
@@ -186,7 +393,7 @@ public:
return MaybeAddAuth(authconf, uri);
}
- aptAuthConfMethod(std::string &&Binary, char const * const Ver, unsigned long const Flags) APT_NONNULL(3) :
- aptMethod(std::move(Binary), Ver, Flags) {}
+ aptAuthConfMethod(std::string &&Binary, char const *const Ver, unsigned long const Flags) APT_NONNULL(3)
+ : aptMethod(std::move(Binary), Ver, Flags) {}
};
#endif
diff --git a/methods/copy.cc b/methods/copy.cc
index fd4786ede..cc2fe9ea4 100644
--- a/methods/copy.cc
+++ b/methods/copy.cc
@@ -30,8 +30,10 @@ class CopyMethod : public aptMethod
virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
public:
-
- CopyMethod() : aptMethod("copy", "1.0",SingleInstance | SendConfig) {};
+ CopyMethod() : aptMethod("copy", "1.0", SingleInstance | SendConfig)
+ {
+ SeccompFlags = aptMethod::BASE;
+ }
};
// CopyMethod::Fetch - Fetch a file /*{{{*/
diff --git a/methods/file.cc b/methods/file.cc
index 6111329d5..269fb432d 100644
--- a/methods/file.cc
+++ b/methods/file.cc
@@ -33,7 +33,10 @@ class FileMethod : public aptMethod
virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE;
public:
- FileMethod() : aptMethod("file", "1.0", SingleInstance | SendConfig | LocalOnly) {};
+ FileMethod() : aptMethod("file", "1.0", SingleInstance | SendConfig | LocalOnly)
+ {
+ SeccompFlags = aptMethod::BASE;
+ }
};
// FileMethod::Fetch - Fetch a file /*{{{*/
diff --git a/methods/ftp.cc b/methods/ftp.cc
index 341230f69..99eebc5af 100644
--- a/methods/ftp.cc
+++ b/methods/ftp.cc
@@ -962,6 +962,7 @@ bool FTPConn::Get(const char *Path,FileFd &To,unsigned long long Resume,
/* */
FtpMethod::FtpMethod() : aptAuthConfMethod("ftp", "1.0", SendConfig)
{
+ SeccompFlags = aptMethod::BASE | aptMethod::NETWORK;
signal(SIGTERM,SigTerm);
signal(SIGINT,SigTerm);
diff --git a/methods/http.cc b/methods/http.cc
index cbc77f477..d939ba7b1 100644
--- a/methods/http.cc
+++ b/methods/http.cc
@@ -984,6 +984,8 @@ BaseHttpMethod::DealWithHeadersResult HttpMethod::DealWithHeaders(FetchResult &R
/*}}}*/
HttpMethod::HttpMethod(std::string &&pProg) : BaseHttpMethod(pProg.c_str(), "1.2", Pipeline | SendConfig)/*{{{*/
{
+ SeccompFlags = aptMethod::BASE | aptMethod::NETWORK;
+
auto addName = std::inserter(methodNames, methodNames.begin());
if (Binary != "http")
addName = "http";
diff --git a/methods/rred.cc b/methods/rred.cc
index 3a3b20286..d4cf1050d 100644
--- a/methods/rred.cc
+++ b/methods/rred.cc
@@ -721,7 +721,10 @@ class RredMethod : public aptMethod {
}
public:
- RredMethod() : aptMethod("rred", "2.0", SendConfig), Debug(false) {}
+ RredMethod() : aptMethod("rred", "2.0", SendConfig), Debug(false)
+ {
+ SeccompFlags = aptMethod::BASE | aptMethod::DIRECTORY;
+ }
};
int main(int argc, char **argv)
diff --git a/methods/store.cc b/methods/store.cc
index d54a14397..7b9e202d9 100644
--- a/methods/store.cc
+++ b/methods/store.cc
@@ -38,6 +38,7 @@ class StoreMethod : public aptMethod
explicit StoreMethod(std::string &&pProg) : aptMethod(std::move(pProg),"1.2",SingleInstance | SendConfig)
{
+ SeccompFlags = aptMethod::BASE;
if (Binary != "store")
methodNames.insert(methodNames.begin(), "store");
}