Remove libseccomp (silly)
This commit is contained in:
parent
523b1f0755
commit
3fd5815677
3 changed files with 0 additions and 288 deletions
|
@ -92,9 +92,6 @@ Pesterchum is a Python script. This means that as long as you have Python instal
|
|||
- Useful for Linux systems that don't meet the Qt6 requirements, as Qt5 Multimedia has a GStreamer dependency.
|
||||
- (Optional) [certifi] can provide alternative root certificates for TLS certificate validation.
|
||||
- Useful for MacOS, as Python doesn't use the system-provided certificates because of MacOS' outdated SSL library. Also miscellaneous systems without usable root certificates.
|
||||
- (Optional) [libseccomp] and its Python bindings on Linux let Pesterchum apply seccomp-bpf restrictions on itself.
|
||||
- Packages on Arch: ``libseccomp python-libseccomp``
|
||||
- Packages on Debian: ``libseccomp2 python-seccomp``
|
||||
|
||||
### WALKTHROUGH
|
||||
|
||||
|
@ -123,7 +120,6 @@ Pesterchum is a Python script. This means that as long as you have Python instal
|
|||
[pygame-ce]: https://pypi.org/project/pygame-ce/
|
||||
[certifi]: https://pypi.org/project/certifi/
|
||||
[GStreamer]: https://gstreamer.freedesktop.org/
|
||||
[libseccomp]: https://github.com/seccomp/libseccomp/
|
||||
|
||||
## FREEZE / BUILD <img src="themes/win95chum/admin.png">
|
||||
Here's a quick guide on how to freeze Pesterchum, (that is, packaging it with python as an executable). :3
|
||||
|
|
245
libseccomp.py
245
libseccomp.py
|
@ -1,245 +0,0 @@
|
|||
"""Functions for Applying a seccomp filter on Linux.
|
||||
|
||||
This prevents the process from using certain system calls, which has some security benefits.
|
||||
Since Python and Qt use many calls and are pretty high-level, things are prone to breaking though.
|
||||
Certain features like opening links almost always break.
|
||||
|
||||
Uses libseccomp's Python bindings, which sadly aren't available on PyPi (yet).
|
||||
Check your distro's package manager for python-libseccomp (Arch) or python3-seccomp (Debian).
|
||||
|
||||
For info on system calls referencing software that uses seccomp like firejail/flatpak is useful.
|
||||
Bindings documentation: https://github.com/seccomp/libseccomp/blob/main/src/python/seccomp.pyx
|
||||
"""
|
||||
import os
|
||||
import logging
|
||||
import threading
|
||||
|
||||
try:
|
||||
import seccomp
|
||||
except ImportError:
|
||||
seccomp = None
|
||||
|
||||
pesterchum_log = logging.getLogger("pchumLogger")
|
||||
|
||||
|
||||
def load_seccomp_blacklist():
|
||||
"""Applies a selective seccomp filter only disallows certain risky calls.
|
||||
|
||||
Should be less likely to cause issues than a full-on whitelist."""
|
||||
if seccomp is None:
|
||||
pesterchum_log.warning(
|
||||
"Failed to import seccomp, verify you have"
|
||||
" python-libseccomp (Arch) or python3-seccomp (Debian) installed."
|
||||
" If this is a pyinstaller/cx_freeze build, it may also be a linking issue."
|
||||
)
|
||||
return
|
||||
# Allows all calls by default.
|
||||
sec_filter = seccomp.SyscallFilter(defaction=seccomp.ALLOW)
|
||||
|
||||
# Deny all socket domains other than AF_UNIX and and AF_INET.
|
||||
sec_filter.add_rule(seccomp.ERRNO(1), "socket", seccomp.Arg(0, seccomp.LT, 1))
|
||||
sec_filter.add_rule(seccomp.ERRNO(1), "socket", seccomp.Arg(0, seccomp.GT, 2))
|
||||
|
||||
# Fully deny these calls.
|
||||
for call in CALL_BLACKLIST:
|
||||
try:
|
||||
sec_filter.add_rule(seccomp.ERRNO(1), call)
|
||||
except RuntimeError:
|
||||
pesterchum_log.warning("Failed to load deny '%s' call seccomp rule.", call)
|
||||
|
||||
sec_filter.load()
|
||||
|
||||
|
||||
def load_seccomp_whitelist():
|
||||
"""Applies a restrictive seccomp filter that disallows most calls by default."""
|
||||
if seccomp is None:
|
||||
pesterchum_log.error(
|
||||
"Failed to import seccomp, verify you have"
|
||||
" python-libseccomp (Arch) or python3-seccomp (Debian) installed."
|
||||
" If this is a pyinstaller/cx_freeze build, it may also be a linking issue."
|
||||
)
|
||||
return
|
||||
# Violation gives "Operation not permitted".
|
||||
sec_filter = seccomp.SyscallFilter(defaction=seccomp.ERRNO(1))
|
||||
# Full access calls
|
||||
for call in CALL_WHITELIST:
|
||||
try:
|
||||
sec_filter.add_rule(seccomp.ALLOW, call)
|
||||
except RuntimeError:
|
||||
pesterchum_log.warning("Failed to load allow '%s' call seccomp rule.", 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.
|
||||
# Allow AF_UNIX
|
||||
sec_filter.add_rule(seccomp.ALLOW, "socket", seccomp.Arg(0, seccomp.EQ, 1))
|
||||
# Allow AF_INET
|
||||
sec_filter.add_rule(seccomp.ALLOW, "socket", seccomp.Arg(0, seccomp.EQ, 2))
|
||||
|
||||
# Python/Qt might close itself via kill call in case of error.
|
||||
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())
|
||||
)
|
||||
|
||||
# Allow openat as long as it's not in R+W mode.
|
||||
# We can't really lock down open/openat further without breaking everything,
|
||||
# even though it's one of the most important calls to lock down.
|
||||
# Could probably allow breaking out of the sandbox in the case of full-on RCE/ACE.
|
||||
sec_filter.add_rule(seccomp.ALLOW, "openat", seccomp.Arg(2, seccomp.NE, 2))
|
||||
|
||||
sec_filter.load()
|
||||
|
||||
|
||||
# Required for Pesterchum to function normally.
|
||||
# We don't call most of these directly, there's a lot of abstraction with Python and Qt.
|
||||
CALL_WHITELIST = [
|
||||
"access", # Files
|
||||
"brk", # Required
|
||||
"clone3", # Required
|
||||
"close", # Sockets (Audio + Network)
|
||||
"connect", # Sockets (Audio + Network)
|
||||
"exit", # Exiting
|
||||
"exit_group", # Exiting
|
||||
"fallocate", # Qt
|
||||
"fcntl", # Required (+ Audio)
|
||||
"fsync", # Fsync log files
|
||||
"ftruncate", # Required
|
||||
"futex", # Required
|
||||
"getcwd", # Get working directory
|
||||
"getdents", # Files? Required.
|
||||
"getgid", # Audio
|
||||
"getpeername", # Connect
|
||||
"getpid", # Audio
|
||||
"getrandom", # Malloc
|
||||
"getsockname", # Required for sockets
|
||||
"getsockopt", # Required for sockets
|
||||
"getuid", # Audio
|
||||
"ioctl", # Socket/Network
|
||||
"lseek", # Files
|
||||
"memfd_create", # Required (For Qt?)
|
||||
"mkdir", # Gotta make folderz sometimez
|
||||
"mmap", # Audio
|
||||
"mprotect", # QThread::start
|
||||
"munmap", # Required (segfault)
|
||||
"newfstatat", # Required (Audio + Path?)
|
||||
"pipe2", # Audio
|
||||
"poll", # Required for literally everything
|
||||
"pselect6", # Sockets/Network
|
||||
"read", # It's read :3
|
||||
"readlink", # Files
|
||||
"recv", # Network
|
||||
"recvfrom", # Network + DNS
|
||||
"recvmsg", # Sockets (incl. Audio + Network)
|
||||
"rseq", # Required
|
||||
"rt_sigprocmask", # Required (segfault)
|
||||
"select", # Useful for sockets
|
||||
"sendmmsg", # Network
|
||||
"sendmsg", # Sockets
|
||||
"sendto", # Eternal eepy!! Sockets + required for waking up mainloop.
|
||||
"setsockopt", # Audio
|
||||
"statx", # File info
|
||||
"uname", # Required
|
||||
"write", # Required
|
||||
]
|
||||
|
||||
# Blacklists of calls we should be able to safely deny.
|
||||
# Setuid might be useful to drop privileges.
|
||||
SETUID = [
|
||||
"setgid",
|
||||
"setgroups",
|
||||
"setregid",
|
||||
"setresgid",
|
||||
"setresuid",
|
||||
"setreuid",
|
||||
"setuid",
|
||||
]
|
||||
SYSTEM = [
|
||||
"acct",
|
||||
"bpf",
|
||||
"capset",
|
||||
"chown",
|
||||
"chroot",
|
||||
"fanotify_init",
|
||||
"fsconfig",
|
||||
"fsmount",
|
||||
"fsopen",
|
||||
"fspick",
|
||||
"kexec_file_load",
|
||||
"kexec_load",
|
||||
"lookup_dcookie",
|
||||
"mount",
|
||||
"move_mount",
|
||||
"nfsservctl",
|
||||
"open_by_handle_at",
|
||||
"open_tree",
|
||||
"perf_event_open",
|
||||
"personality",
|
||||
"pidfd_getfd",
|
||||
"pivot_root",
|
||||
"pivot_root",
|
||||
"process_vm_readv",
|
||||
"process_vm_writev",
|
||||
"ptrace", # <-- Important
|
||||
"quotactl",
|
||||
"reboot",
|
||||
"rtas",
|
||||
"s390_runtime_instr",
|
||||
"setdomainname",
|
||||
"setfsuid",
|
||||
"sethostname",
|
||||
"swapoff",
|
||||
"swapon",
|
||||
"sys_debug_setcontext",
|
||||
"umount",
|
||||
"umount2",
|
||||
"vhangup",
|
||||
]
|
||||
CALL_BLACKLIST = SYSTEM # + SETUID
|
||||
|
||||
"""
|
||||
# Optional
|
||||
EXTRA_CALLS = [
|
||||
"mlock",
|
||||
"munlock",
|
||||
"socketcall",
|
||||
"socketpair",
|
||||
"readlink",
|
||||
"getsockname",
|
||||
"getpeername",
|
||||
"writev",
|
||||
"open",
|
||||
"time",
|
||||
"listen",
|
||||
]
|
||||
# Required on launch
|
||||
LAUNCH_CALLS = [
|
||||
"prctl",
|
||||
"faccessat",
|
||||
"faccessat2",
|
||||
"pwrite64",
|
||||
]
|
||||
# Required before full initialize
|
||||
PRE_INITIALIZE_CALLS = [
|
||||
"bind",
|
||||
"eventfd2",
|
||||
"getegid",
|
||||
"geteuid",
|
||||
"getresgid",
|
||||
"getresuid",
|
||||
"gettid",
|
||||
"recvmmsg",
|
||||
"restart_syscall",
|
||||
"rt_sigaction",
|
||||
"rt_sigreturn",
|
||||
"sched_getaffinity",
|
||||
"sched_getattr",
|
||||
"sched_setattr",
|
||||
"shutdown",
|
||||
"umask",
|
||||
]
|
||||
# Required for opening links, but opening links still doesn't work anyway.
|
||||
LINK_CALLS = [
|
||||
"wait4", # for links?
|
||||
"clone", # for links?
|
||||
]
|
||||
"""
|
|
@ -19,9 +19,6 @@ import ostools
|
|||
import nickservmsgs
|
||||
import pytwmn
|
||||
|
||||
if ostools.isLinux():
|
||||
import libseccomp
|
||||
|
||||
# import console
|
||||
from user_profile import (
|
||||
userConfig,
|
||||
|
@ -114,21 +111,6 @@ parser.add_argument(
|
|||
parser.add_argument(
|
||||
"--nohonk", action="store_true", help="Disables the honk soundeffect 🤡📣"
|
||||
)
|
||||
if ostools.isLinux():
|
||||
parser.add_argument(
|
||||
"--no-seccomp",
|
||||
action="store_true",
|
||||
help=("Disable seccomp completely. (do this if it causes issues)"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--strict-seccomp",
|
||||
action="store_true",
|
||||
help=(
|
||||
"Apply a stricter seccomp-bpf filter that only allows required system calls."
|
||||
" This breaks certain features like opening links."
|
||||
" (Requires Linux and libseccomp's Python bindings.)"
|
||||
),
|
||||
)
|
||||
|
||||
# Set logging config section, log level is in oppts.
|
||||
# Logger
|
||||
|
@ -1692,22 +1674,6 @@ class PesterWindow(MovingWindow):
|
|||
if ostools.isLinux():
|
||||
# Set no_new_privs bit.
|
||||
self.set_no_new_privs()
|
||||
# Activate seccomp.
|
||||
self.seccomp(options)
|
||||
|
||||
def seccomp(self, options):
|
||||
"""Load seccomp-bpf filter depending on arguments passed."""
|
||||
if "no-seccomp" in options:
|
||||
if options["no-seccomp"]:
|
||||
return
|
||||
try:
|
||||
libseccomp.load_seccomp_blacklist() # Load blacklist filter by default
|
||||
if "strict-seccomp" in options:
|
||||
if options["strict-seccomp"]:
|
||||
libseccomp.load_seccomp_whitelist() # Load whitelist filter if enabled
|
||||
except RuntimeError:
|
||||
# We probably tried to interact with a call not available on this kernel.
|
||||
PchumLog.exception("")
|
||||
|
||||
@QtCore.pyqtSlot(str, str)
|
||||
def updateMsg(self, ver, url):
|
||||
|
@ -4592,11 +4558,6 @@ class MainProgram(QtCore.QObject):
|
|||
# Disable honks
|
||||
if args.nohonk:
|
||||
options["honk"] = False
|
||||
if ostools.isLinux():
|
||||
if args.strict_seccomp:
|
||||
options["strict-seccomp"] = True
|
||||
if args.no_seccomp:
|
||||
options["no-seccomp"] = True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return options
|
||||
|
|
Loading…
Reference in a new issue