Add seccomp option on Linux via libseccomp Python bindings.
This commit is contained in:
parent
dabfb81b04
commit
6c3d5dbb21
2 changed files with 157 additions and 0 deletions
136
libseccomp.py
Normal file
136
libseccomp.py
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
"""
|
||||||
|
Applies a seccomp filter on Linux via libseccomp's Python bindings.
|
||||||
|
May have some security benefits, but since Python and Qt use many calls
|
||||||
|
and are pretty high-level, things are very prone to breaking.
|
||||||
|
|
||||||
|
Libseccomp's Python bindings aren't available on the pypi, check your distro's
|
||||||
|
package manager for python-libseccomp (Arch) or python3-seccomp (Debian).
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
|
||||||
|
try:
|
||||||
|
import seccomp
|
||||||
|
except ImportError:
|
||||||
|
seccomp = None
|
||||||
|
|
||||||
|
pesterchum_log = logging.getLogger("pchumLogger")
|
||||||
|
|
||||||
|
|
||||||
|
def activate_seccomp():
|
||||||
|
"""Sets the process into seccomp filter mode."""
|
||||||
|
if seccomp is None:
|
||||||
|
pesterchum_log.error("Failed to import seccomp.")
|
||||||
|
return
|
||||||
|
# Violation gives "Operation not permitted".
|
||||||
|
sec_filter = seccomp.SyscallFilter(defaction=seccomp.ERRNO(1))
|
||||||
|
# Full access calls
|
||||||
|
for call in PCHUM_SYSTEM_CALLS:
|
||||||
|
sec_filter.add_rule(seccomp.ALLOW, call)
|
||||||
|
|
||||||
|
# Allow only UNIX and INET sockets, see the linux manual and source on socket for reference.
|
||||||
|
# Arg(0, seccomp.EQ, 1) means argument 0 must be equal to 1, 1 being the value of AF_UNIX.
|
||||||
|
sec_filter.add_rule(seccomp.ALLOW, "socket", seccomp.Arg(0, seccomp.EQ, 1)) # AF_UNIX
|
||||||
|
sec_filter.add_rule(seccomp.ALLOW, "socket", seccomp.Arg(0, seccomp.EQ, 2)) # AF_INET
|
||||||
|
|
||||||
|
# We can kill ourselves in case of skill issues but not others.
|
||||||
|
sec_filter.add_rule(seccomp.ALLOW, "kill", seccomp.Arg(0, seccomp.EQ, os.getpid()))
|
||||||
|
sec_filter.add_rule(seccomp.ALLOW, "tgkill", seccomp.Arg(1, seccomp.EQ, threading.get_native_id()))
|
||||||
|
|
||||||
|
sec_filter.load()
|
||||||
|
|
||||||
|
def restrict_open():
|
||||||
|
# Allow only opening for reading/writing
|
||||||
|
sec_filter.add_rule(seccomp.ALLOW, "openat", seccomp.Arg(0, seccomp.EQ, os.getpid()))
|
||||||
|
|
||||||
|
# Required for Pesterchum to run.
|
||||||
|
PCHUM_SYSTEM_CALLS = [
|
||||||
|
"access",
|
||||||
|
"bind",
|
||||||
|
"brk",
|
||||||
|
"clone3",
|
||||||
|
"close",
|
||||||
|
"connect",
|
||||||
|
"eventfd2",
|
||||||
|
"exit",
|
||||||
|
"exit_group",
|
||||||
|
"faccessat",
|
||||||
|
"faccessat2",
|
||||||
|
"fallocate",
|
||||||
|
"fcntl",
|
||||||
|
"fsync",
|
||||||
|
"ftruncate",
|
||||||
|
"futex",
|
||||||
|
"getcwd",
|
||||||
|
"getdents64",
|
||||||
|
"getegid",
|
||||||
|
"geteuid",
|
||||||
|
"getgid",
|
||||||
|
"getpeername",
|
||||||
|
"getpid",
|
||||||
|
"getrandom",
|
||||||
|
"getresgid",
|
||||||
|
"getresuid",
|
||||||
|
"getsockname",
|
||||||
|
"getsockopt",
|
||||||
|
"gettid",
|
||||||
|
"getuid",
|
||||||
|
"ioctl",
|
||||||
|
"lseek",
|
||||||
|
"memfd_create",
|
||||||
|
"mkdir",
|
||||||
|
"mmap",
|
||||||
|
"mprotect",
|
||||||
|
"munmap",
|
||||||
|
"newfstatat",
|
||||||
|
"openat",
|
||||||
|
"pipe2",
|
||||||
|
"poll",
|
||||||
|
"prctl",
|
||||||
|
"pselect6",
|
||||||
|
"pwrite64",
|
||||||
|
"read",
|
||||||
|
"recv",
|
||||||
|
"recvfrom",
|
||||||
|
"recvfrom",
|
||||||
|
"recvmmsg",
|
||||||
|
"recvmsg",
|
||||||
|
"restart_syscall",
|
||||||
|
"rseq",
|
||||||
|
"rt_sigaction",
|
||||||
|
"rt_sigprocmask",
|
||||||
|
"rt_sigreturn",
|
||||||
|
"sched_getaffinity",
|
||||||
|
"sched_getattr",
|
||||||
|
"sched_setattr",
|
||||||
|
"select",
|
||||||
|
"sendmmsg",
|
||||||
|
"sendmsg",
|
||||||
|
"sendto",
|
||||||
|
"setsockopt",
|
||||||
|
"shutdown",
|
||||||
|
"statx",
|
||||||
|
"umask",
|
||||||
|
"uname",
|
||||||
|
"write",
|
||||||
|
]
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Optional
|
||||||
|
EXTRA_CALLS = [
|
||||||
|
"mlock",
|
||||||
|
"munlock",
|
||||||
|
"socketcall",
|
||||||
|
"socketpair",
|
||||||
|
"readlink",
|
||||||
|
"getsockname",
|
||||||
|
"getpeername",
|
||||||
|
"writev",
|
||||||
|
"open",
|
||||||
|
"time",
|
||||||
|
"listen",
|
||||||
|
"wait4", # for links?
|
||||||
|
"clone", # for links?
|
||||||
|
]
|
||||||
|
"""
|
|
@ -17,6 +17,8 @@ if os.path.dirname(sys.argv[0]):
|
||||||
import ostools
|
import ostools
|
||||||
import nickservmsgs
|
import nickservmsgs
|
||||||
import pytwmn
|
import pytwmn
|
||||||
|
if ostools.isLinux():
|
||||||
|
import libseccomp
|
||||||
|
|
||||||
# import console
|
# import console
|
||||||
from pnc.dep.attrdict import AttrDict
|
from pnc.dep.attrdict import AttrDict
|
||||||
|
@ -105,6 +107,17 @@ parser.add_argument(
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--nohonk", action="store_true", help="Disables the honk soundeffect 🤡📣"
|
"--nohonk", action="store_true", help="Disables the honk soundeffect 🤡📣"
|
||||||
)
|
)
|
||||||
|
if ostools.isLinux():
|
||||||
|
parser.add_argument(
|
||||||
|
"--seccomp",
|
||||||
|
action="store_true",
|
||||||
|
help=(
|
||||||
|
"Restrict the system calls Pesterchum is allowed to make via seccomp."
|
||||||
|
" May have some security benefits, but since Python and Qt use many calls"
|
||||||
|
" and are pretty high-level, things are very prone to breaking."
|
||||||
|
" (Requires Linux and libseccomp's Python bindings, not available in frozen builds.)"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# Set logging config section, log level is in oppts.
|
# Set logging config section, log level is in oppts.
|
||||||
# Logger
|
# Logger
|
||||||
|
@ -1388,6 +1401,10 @@ class PesterWindow(MovingWindow):
|
||||||
self.honk = options["honk"]
|
self.honk = options["honk"]
|
||||||
else:
|
else:
|
||||||
self.honk = True
|
self.honk = True
|
||||||
|
# Activate seccomp if enabled
|
||||||
|
if "seccomp" in options:
|
||||||
|
if options["seccomp"]:
|
||||||
|
libseccomp.activate_seccomp()
|
||||||
self.modes = ""
|
self.modes = ""
|
||||||
|
|
||||||
self.sound_type = None
|
self.sound_type = None
|
||||||
|
@ -4548,6 +4565,10 @@ class MainProgram(QtCore.QObject):
|
||||||
# Disable honks
|
# Disable honks
|
||||||
if args.nohonk:
|
if args.nohonk:
|
||||||
options["honk"] = False
|
options["honk"] = False
|
||||||
|
if ostools.isLinux():
|
||||||
|
if args.seccomp:
|
||||||
|
options["seccomp"] = True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
return options
|
return options
|
||||||
|
|
Loading…
Reference in a new issue