Mini Shell
# -*- coding: utf-8 -*-
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
# Module contains functions for remounting /proc with hidepid=2 option
# see CAG-796 for details
import subprocess
import re
from clcommon.cpapi import Feature, is_panel_feature_supported
from clcommon.sysctl import SysCtlConf, SYSCTL_CL_CONF_FILE
from clcommon.utils import grep, proc_can_see_other_uid_and_hidepid_synced
# on some systems hidepid value is str
HidepidValuesDict = {
'noaccess': 1,
'invisible': 2,
'1': 1,
'2': 2,
}
def hidepid_found():
"""
Search for line like "proc /proc proc defaults,hidepid=2,gid=clsupergid 0 0" in /etc/fstab
Return True if /proc is mounted with hidepid option in /etc/fstab
"""
fstab = '/etc/fstab'
try:
with open(fstab, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
splitted_line = line.split()
if splitted_line and splitted_line[0] == 'proc' and 'hidepid=' in splitted_line[3]:
return True
except (IOError, IndexError) as e:
print('Error: failed to parse', fstab, ':', str(e))
return False
def execute(cmd, verbose):
if verbose:
print('executing', ' '.join(cmd))
return subprocess.call(cmd)
def remount_proc(verbose=False):
"""
Remount /proc with hidepid=2 option when needed
"""
# In latest versions of the kernel on CL8
# no need to remount /proc with hidepid option
# because it is synchronized with fs.proc_can_see_other_uid option
if proc_can_see_other_uid_and_hidepid_synced():
return
if not is_panel_feature_supported(Feature.LVE):
if verbose:
print('environment without LVE detected - remounting /proc is skipped')
return
sysctl = SysCtlConf(config_file=SYSCTL_CL_CONF_FILE)
if verbose:
print('apply sysctl settings')
if hidepid_found():
# admin can override hidepid option via /etc/fstab
if verbose:
print('hidepid option is found in /etc/fstab - remounting /proc with options from /etc/fstab')
return execute(['/bin/mount', '-o', 'remount', '/proc'], verbose)
proc_can_see_other_uid = sysctl.get('fs.proc_can_see_other_uid')
super_gid = sysctl.get('fs.proc_super_gid')
if proc_can_see_other_uid != '0':
if verbose:
print('virtualized procfs feature is not enabled in sysctl conf - disable hidepid')
return execute(['/bin/mount', '-o', 'remount,hidepid=0,gid=0', '/proc'], verbose)
if verbose:
print('enable hidepid for /proc')
return execute(['/bin/mount', '-o', 'remount,hidepid=2,gid=' + super_gid, '/proc'], verbose)
def get_gid_from_mounts():
"""
Retrieve hidepid gid from /proc/mounts
:return: gid, 0 if absent
"""
lines_gen = grep(',hidepid=', '/proc/mounts')
gid_prefix = ',gid='
try:
for line in lines_gen:
line = line.strip()
if gid_prefix not in line:
continue
# Search gid=xxxx in line
pos = line.find(gid_prefix)
if pos == -1:
continue
pos += 5
line = line[pos:]
pos = line.find(',')
if pos != -1:
line = line[:pos]
else:
pos = line.find(' ')
if pos != -1:
line = line[:pos]
else:
# Invalid or unsupported proc format
return -1
return int(line)
except (IOError, IndexError, ValueError):
pass
# hidepid not found in /proc/mounts
return -1
def get_hidepid_typing_from_mounts() -> int:
"""
Retrieve hidepid value from /proc/mounts
:return: hidepid, 0 if absent
"""
mounts_path = '/proc/mounts'
res = 0
try:
# Parse mounts file output for proc lines and get the hidepid
with open(mounts_path, mode='r', encoding='utf-8') as file:
for line in file:
m = re.search(r'hidepid=(\d|\w+)', line)
if not line.strip().startswith('proc /proc'):
continue
if m:
res = HidepidValuesDict.get(str(m.group(1)), 0)
break
except (OSError, IOError, IndexError, ValueError):
pass
# hidepid not found in /proc/mounts
return res
Zerion Mini Shell 1.0