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.
|
- 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.
|
- (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.
|
- 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
|
### 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/
|
[pygame-ce]: https://pypi.org/project/pygame-ce/
|
||||||
[certifi]: https://pypi.org/project/certifi/
|
[certifi]: https://pypi.org/project/certifi/
|
||||||
[GStreamer]: https://gstreamer.freedesktop.org/
|
[GStreamer]: https://gstreamer.freedesktop.org/
|
||||||
[libseccomp]: https://github.com/seccomp/libseccomp/
|
|
||||||
|
|
||||||
## FREEZE / BUILD <img src="themes/win95chum/admin.png">
|
## 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
|
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 nickservmsgs
|
||||||
import pytwmn
|
import pytwmn
|
||||||
|
|
||||||
if ostools.isLinux():
|
|
||||||
import libseccomp
|
|
||||||
|
|
||||||
# import console
|
# import console
|
||||||
from user_profile import (
|
from user_profile import (
|
||||||
userConfig,
|
userConfig,
|
||||||
|
@ -114,21 +111,6 @@ 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(
|
|
||||||
"--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.
|
# Set logging config section, log level is in oppts.
|
||||||
# Logger
|
# Logger
|
||||||
|
@ -1692,22 +1674,6 @@ class PesterWindow(MovingWindow):
|
||||||
if ostools.isLinux():
|
if ostools.isLinux():
|
||||||
# Set no_new_privs bit.
|
# Set no_new_privs bit.
|
||||||
self.set_no_new_privs()
|
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)
|
@QtCore.pyqtSlot(str, str)
|
||||||
def updateMsg(self, ver, url):
|
def updateMsg(self, ver, url):
|
||||||
|
@ -4592,11 +4558,6 @@ 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.strict_seccomp:
|
|
||||||
options["strict-seccomp"] = True
|
|
||||||
if args.no_seccomp:
|
|
||||||
options["no-seccomp"] = True
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
return options
|
return options
|
||||||
|
|
Loading…
Reference in a new issue