security updates
This commit is contained in:
parent
77325b42d6
commit
2a3209ca72
104
nohang/nohang
104
nohang/nohang
@ -11,6 +11,7 @@ from sre_constants import error as invalid_re
|
|||||||
from signal import signal, SIGKILL, SIGTERM, SIGINT, SIGQUIT, SIGHUP
|
from signal import signal, SIGKILL, SIGTERM, SIGINT, SIGQUIT, SIGHUP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
# define functions
|
# define functions
|
||||||
@ -19,25 +20,27 @@ from signal import signal, SIGKILL, SIGTERM, SIGINT, SIGQUIT, SIGHUP
|
|||||||
def exe(cmd):
|
def exe(cmd):
|
||||||
""" execute cmd in subprocess.Popen()
|
""" execute cmd in subprocess.Popen()
|
||||||
"""
|
"""
|
||||||
|
cmd_list = shlex.split(cmd)
|
||||||
|
|
||||||
cmd_num_dict['cmd_num'] += 1
|
cmd_num_dict['cmd_num'] += 1
|
||||||
cmd_num = cmd_num_dict['cmd_num']
|
cmd_num = cmd_num_dict['cmd_num']
|
||||||
log('Execute the command({}) in {}: {}'.format(
|
|
||||||
|
log('Execute the command ({}) in {}: {}'.format(
|
||||||
cmd_num,
|
cmd_num,
|
||||||
threading.current_thread().getName(),
|
threading.current_thread().getName(),
|
||||||
cmd))
|
cmd_list))
|
||||||
t3 = monotonic()
|
t3 = monotonic()
|
||||||
with Popen(cmd, shell=True) as proc:
|
with Popen(cmd_list) as proc:
|
||||||
try:
|
try:
|
||||||
proc.wait(timeout=exe_timeout)
|
proc.wait(timeout=exe_timeout)
|
||||||
exit_status = proc.poll()
|
exit_status = proc.poll()
|
||||||
t4 = monotonic()
|
t4 = monotonic()
|
||||||
log('Command({}) execution completed in {} sec; exit status' \
|
log('Command ({}) execution completed in {} sec; exit status' \
|
||||||
': {}'.format(cmd_num, round(t4 - t3, 3), exit_status))
|
': {}'.format(cmd_num, round(t4 - t3, 3), exit_status))
|
||||||
except TimeoutExpired:
|
except TimeoutExpired:
|
||||||
proc.kill()
|
proc.kill()
|
||||||
t4 = monotonic()
|
t4 = monotonic()
|
||||||
log('TimeoutExpired for the command({}) in {} sec'.format(
|
log('TimeoutExpired for the command ({}) in {} sec'.format(
|
||||||
cmd_num, round(t4 - t3, 3)))
|
cmd_num, round(t4 - t3, 3)))
|
||||||
|
|
||||||
|
|
||||||
@ -61,9 +64,9 @@ def start_thread(func, *a, **k):
|
|||||||
t2 = monotonic()
|
t2 = monotonic()
|
||||||
|
|
||||||
if debug_threading:
|
if debug_threading:
|
||||||
log('{} has started in {} ms, {} threads currently alive'.format(
|
log('{} has started in {} ms, {} threads are ' \
|
||||||
th_name, round((t2 - t1) * 1000, 1), threading.active_count()
|
'currently alive'.format(th_name, round((
|
||||||
))
|
t2 - t1) * 1000, 1), threading.active_count()))
|
||||||
|
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
|
||||||
@ -153,6 +156,17 @@ def pop(cmd, username):
|
|||||||
""" run cmd in subprocess.Popen()
|
""" run cmd in subprocess.Popen()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
cmd_num_dict['cmd_num'] += 1
|
||||||
|
cmd_num = cmd_num_dict['cmd_num']
|
||||||
|
|
||||||
|
log('Execute the Command-{} {} in {}'.format(
|
||||||
|
cmd_num,
|
||||||
|
cmd,
|
||||||
|
threading.current_thread().getName()
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
if swap_total == 0:
|
if swap_total == 0:
|
||||||
wait_time = 2
|
wait_time = 2
|
||||||
else:
|
else:
|
||||||
@ -164,18 +178,15 @@ def pop(cmd, username):
|
|||||||
try:
|
try:
|
||||||
proc.wait(timeout=wait_time)
|
proc.wait(timeout=wait_time)
|
||||||
err = proc.poll()
|
err = proc.poll()
|
||||||
|
t4 = monotonic()
|
||||||
except TimeoutExpired:
|
except TimeoutExpired:
|
||||||
proc.kill()
|
proc.kill()
|
||||||
|
t4 = monotonic()
|
||||||
|
|
||||||
if debug_gui_notifications:
|
if debug_gui_notifications:
|
||||||
log('TimeoutExpired: notify user: {}'.format(username))
|
log('TimeoutExpired: notify user: {}'.format(username))
|
||||||
|
|
||||||
t4 = monotonic()
|
|
||||||
|
|
||||||
err = 0
|
|
||||||
|
|
||||||
if debug_gui_notifications:
|
if debug_gui_notifications:
|
||||||
pass
|
|
||||||
#log('Popen time: {} sec; exit status: {}; cmd: {}'.format(round(t4 - t3, 3), err, cmd))
|
|
||||||
log('Popen time: {} sec; exit status: {}; cmd: {}'.format(round(t4 - t3, 3), err, cmd))
|
log('Popen time: {} sec; exit status: {}; cmd: {}'.format(round(t4 - t3, 3), err, cmd))
|
||||||
|
|
||||||
|
|
||||||
@ -279,6 +290,10 @@ def send_notify(threshold, name, pid):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
title = 'Freeze prevention'
|
title = 'Freeze prevention'
|
||||||
|
|
||||||
|
if hide_corrective_action_type:
|
||||||
|
body = 'Corrective action applied'
|
||||||
|
else:
|
||||||
body = '<b>{}</b> [{}] <b>{}</b>'.format(
|
body = '<b>{}</b> [{}] <b>{}</b>'.format(
|
||||||
notify_sig_dict[threshold],
|
notify_sig_dict[threshold],
|
||||||
pid,
|
pid,
|
||||||
@ -286,8 +301,7 @@ def send_notify(threshold, name, pid):
|
|||||||
# symbol '&' can break notifications in some themes,
|
# symbol '&' can break notifications in some themes,
|
||||||
# therefore it is replaced by '*'
|
# therefore it is replaced by '*'
|
||||||
'&', '*'
|
'&', '*'
|
||||||
)
|
))
|
||||||
)
|
|
||||||
|
|
||||||
start_thread(send_notification, title, body)
|
start_thread(send_notification, title, body)
|
||||||
|
|
||||||
@ -301,9 +315,12 @@ def send_notify_etc(pid, name, command):
|
|||||||
pid: str process pid
|
pid: str process pid
|
||||||
"""
|
"""
|
||||||
title = 'Freeze prevention'
|
title = 'Freeze prevention'
|
||||||
body = '<b>Victim is</b> [{}] <b>{}</b>\nExecute the co' \
|
if hide_corrective_action_type:
|
||||||
'mmand:\n<b>{}</b>'.format(
|
body = 'Corrective action applied'
|
||||||
pid, name.replace('&', '*'), command.replace('&', '*'))
|
else:
|
||||||
|
body = '<b>Victim is</b> [{}] <b>{}</b>\nExecute the command:\n<b>' \
|
||||||
|
'{}</b>'.format(pid, name.replace(
|
||||||
|
'&', '*'), command.replace('&', '*'))
|
||||||
|
|
||||||
start_thread(send_notification, title, body)
|
start_thread(send_notification, title, body)
|
||||||
|
|
||||||
@ -3016,9 +3033,24 @@ print_victim_cmdline = conf_parse_bool('print_victim_cmdline')
|
|||||||
print_config_at_startup = conf_parse_bool('print_config_at_startup')
|
print_config_at_startup = conf_parse_bool('print_config_at_startup')
|
||||||
print_mem_check_results = conf_parse_bool('print_mem_check_results')
|
print_mem_check_results = conf_parse_bool('print_mem_check_results')
|
||||||
debug_sleep = conf_parse_bool('debug_sleep')
|
debug_sleep = conf_parse_bool('debug_sleep')
|
||||||
|
|
||||||
|
hide_corrective_action_type = conf_parse_bool('hide_corrective_action_type')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
low_memory_warnings_enabled = conf_parse_bool('low_memory_warnings_enabled')
|
low_memory_warnings_enabled = conf_parse_bool('low_memory_warnings_enabled')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
post_action_gui_notifications = conf_parse_bool(
|
post_action_gui_notifications = conf_parse_bool(
|
||||||
'post_action_gui_notifications')
|
'post_action_gui_notifications')
|
||||||
|
|
||||||
@ -3369,33 +3401,35 @@ if separate_log:
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
log_dir = '/var/log/nohang'
|
log_dir = '/var/log/nohang'
|
||||||
|
|
||||||
try:
|
|
||||||
os.mkdir(log_dir)
|
|
||||||
except PermissionError:
|
|
||||||
print('ERROR: can not create log dir')
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
logfile = log_dir + '/nohang.log'
|
logfile = log_dir + '/nohang.log'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(logfile, 'a') as f:
|
os.mkdir(log_dir)
|
||||||
|
except FileExistsError:
|
||||||
pass
|
pass
|
||||||
except FileNotFoundError:
|
|
||||||
print('ERROR: log FileNotFoundError')
|
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
print('ERROR: log PermissionError')
|
errprint('ERROR: cannot create {}'.format(log_dir))
|
||||||
|
|
||||||
|
try:
|
||||||
|
os.chmod(log_dir, mode=0o750)
|
||||||
|
except FileNotFoundError:
|
||||||
|
errprint('ERROR: file not found: {}'.format(log_dir))
|
||||||
|
except PermissionError:
|
||||||
|
errprint('ERROR: permission denied: {}'.format(log_dir))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
filename=logfile,
|
filename=logfile,
|
||||||
level=logging.INFO,
|
level=logging.INFO,
|
||||||
format="%(asctime)s: %(message)s")
|
format="%(asctime)s: %(message)s")
|
||||||
except PermissionError:
|
|
||||||
errprint('ERROR: Permission denied: {}'.format(logfile))
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
errprint('ERROR: FileNotFoundError: {}'.format(logfile))
|
errprint('ERROR: file not found: {}'.format(logfile))
|
||||||
|
except PermissionError:
|
||||||
|
errprint('ERROR: permission denied: {}'.format(logfile))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 'min_mem_report_interval' in config_dict:
|
if 'min_mem_report_interval' in config_dict:
|
||||||
@ -3511,11 +3545,13 @@ if (low_memory_warnings_enabled or \
|
|||||||
post_kill_exe != ''):
|
post_kill_exe != ''):
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
import shlex
|
||||||
from subprocess import Popen, TimeoutExpired
|
from subprocess import Popen, TimeoutExpired
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
psi_support = os.path.exists(psi_path)
|
psi_support = os.path.exists(psi_path)
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,6 +112,8 @@ over_sleep = 0.05
|
|||||||
|
|
||||||
4. Warnings and notifications
|
4. Warnings and notifications
|
||||||
|
|
||||||
|
4.1. GUI notifications after corrective actions
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
Type: boolean
|
Type: boolean
|
||||||
Valid values: True and False
|
Valid values: True and False
|
||||||
@ -122,6 +124,14 @@ post_action_gui_notifications = True
|
|||||||
Type: boolean
|
Type: boolean
|
||||||
Valid values: True and False
|
Valid values: True and False
|
||||||
|
|
||||||
|
hide_corrective_action_type = True
|
||||||
|
|
||||||
|
4.2. Low memory warnings
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Type: boolean
|
||||||
|
Valid values: True and False
|
||||||
|
|
||||||
low_memory_warnings_enabled = True
|
low_memory_warnings_enabled = True
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
@ -112,6 +112,8 @@ over_sleep = 0.05
|
|||||||
|
|
||||||
4. Warnings and notifications
|
4. Warnings and notifications
|
||||||
|
|
||||||
|
4.1. GUI notifications after corrective actions
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
Type: boolean
|
Type: boolean
|
||||||
Valid values: True and False
|
Valid values: True and False
|
||||||
@ -122,6 +124,14 @@ post_action_gui_notifications = False
|
|||||||
Type: boolean
|
Type: boolean
|
||||||
Valid values: True and False
|
Valid values: True and False
|
||||||
|
|
||||||
|
hide_corrective_action_type = True
|
||||||
|
|
||||||
|
4.2. Low memory warnings
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Type: boolean
|
||||||
|
Valid values: True and False
|
||||||
|
|
||||||
low_memory_warnings_enabled = False
|
low_memory_warnings_enabled = False
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
@ -8,18 +8,20 @@ ExecStart=:TARGET_BIN:/nohang --config :TARGET_CONF:/nohang/nohang.conf
|
|||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=0
|
RestartSec=0
|
||||||
KillMode=mixed
|
KillMode=mixed
|
||||||
|
TasksMax=100
|
||||||
Nice=-15
|
Nice=-15
|
||||||
CPUSchedulingResetOnFork=true
|
CPUSchedulingResetOnFork=true
|
||||||
OOMScoreAdjust=-10
|
OOMScoreAdjust=-10
|
||||||
|
UMask=0027
|
||||||
|
PrivateTmp=true
|
||||||
RestrictRealtime=yes
|
RestrictRealtime=yes
|
||||||
MemoryDenyWriteExecute=yes
|
MemoryDenyWriteExecute=yes
|
||||||
ProtectKernelModules=true
|
ProtectKernelModules=true
|
||||||
SystemCallArchitectures=native
|
SystemCallArchitectures=native
|
||||||
ReadOnlyPaths=/
|
ReadOnlyPaths=/
|
||||||
ReadWritePaths=/tmp /var /run /dev/shm
|
ReadWritePaths=/tmp /var /run /dev/shm
|
||||||
PrivateTmp=true
|
CapabilityBoundingSet=CAP_KILL CAP_IPC_LOCK CAP_SYS_PTRACE CAP_DAC_READ_SEARCH CAP_AUDIT_WRITE CAP_SETUID CAP_SETGID
|
||||||
CapabilityBoundingSet=CAP_KILL CAP_AUDIT_WRITE CAP_DAC_READ_SEARCH CAP_IPC_LOCK CAP_SETGID CAP_SETUID CAP_SYS_PTRACE CAP_CHOWN
|
AmbientCapabilities=CAP_KILL CAP_IPC_LOCK CAP_SYS_PTRACE CAP_DAC_READ_SEARCH CAP_AUDIT_WRITE CAP_SETUID CAP_SETGID
|
||||||
AmbientCapabilities=CAP_KILL CAP_AUDIT_WRITE CAP_DAC_READ_SEARCH CAP_IPC_LOCK CAP_SETGID CAP_SETUID CAP_SYS_PTRACE
|
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
@ -112,6 +112,8 @@ over_sleep = 0.05
|
|||||||
|
|
||||||
4. Warnings and notifications
|
4. Warnings and notifications
|
||||||
|
|
||||||
|
4.1. GUI notifications after corrective actions
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
Type: boolean
|
Type: boolean
|
||||||
Valid values: True and False
|
Valid values: True and False
|
||||||
@ -122,6 +124,14 @@ post_action_gui_notifications = True
|
|||||||
Type: boolean
|
Type: boolean
|
||||||
Valid values: True and False
|
Valid values: True and False
|
||||||
|
|
||||||
|
hide_corrective_action_type = False
|
||||||
|
|
||||||
|
4.2. Low memory warnings
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Type: boolean
|
||||||
|
Valid values: True and False
|
||||||
|
|
||||||
low_memory_warnings_enabled = True
|
low_memory_warnings_enabled = True
|
||||||
|
|
||||||
Description:
|
Description:
|
||||||
|
Loading…
Reference in New Issue
Block a user