From 9fb4cf6f17e3e028d4e01514a947ccb2828738ac Mon Sep 17 00:00:00 2001 From: Yaroslav Brustinov Date: Mon, 2 Jan 2017 19:10:25 +0200 Subject: add warning about lack of read permissions for user "nobody" to run scapy server. add flag to disable scapy server run. Change-Id: I65ccfb24ed4a5461fe2a13d8be0f07fad8a50bae Signed-off-by: Yaroslav Brustinov --- scripts/scapy_daemon_server | 93 ++++++++++++++++++++++++++++++++------------- 1 file changed, 66 insertions(+), 27 deletions(-) (limited to 'scripts/scapy_daemon_server') diff --git a/scripts/scapy_daemon_server b/scripts/scapy_daemon_server index a5e4df06..e19c8b3c 100755 --- a/scripts/scapy_daemon_server +++ b/scripts/scapy_daemon_server @@ -6,6 +6,7 @@ import time import subprocess, shlex from argparse import ArgumentParser, RawTextHelpFormatter import errno +import pwd def fail(msg): print(msg) @@ -14,8 +15,8 @@ def fail(msg): if os.getuid() != 0: fail('Please run this program as root/with sudo') -pwd = os.path.abspath(os.path.dirname(__file__)) -ext_libs_path = os.path.join(pwd, 'external_libs') +cur_dir = os.path.abspath(os.path.dirname(__file__)) +ext_libs_path = os.path.join(cur_dir, 'external_libs') if ext_libs_path not in sys.path: sys.path.append(ext_libs_path) @@ -30,34 +31,46 @@ def inv(f): return lambda *a, **k: not f(*a, **k) -def progress(success_check, start_msg, success_msg, fail_msg, timeout = 10, poll_rate = 0.5): +def progress(success_check, start_msg, success_msg, fail_msg, timeout = 35, poll_rate = 0.5, fail_check = None): sys.stdout.write('%s...' % start_msg) sys.stdout.flush() for i in range(int(timeout/poll_rate)): if success_check(): print(termstyle.green(' ' + success_msg)) return 0 + if fail_check and fail_check(): + print(termstyle.red(' ' + fail_msg)) + return 1 time.sleep(poll_rate) sys.stdout.write('.') sys.stdout.flush() - if success_check(): - print(termstyle.green(' ' + success_msg)) - return 0 - print(termstyle.red(' ' + fail_msg)) + print(termstyle.red(' Timeout')) return 1 -def run_command(command, timeout = 15, poll_rate = 0.1, cwd = None): - assert timeout > 0, 'Timeout should be positive' - assert poll_rate > 0, 'Poll rate should be positive' +def demote_func(): + pw_record = pwd.getpwnam('nobody') + os.setgid(pw_record.pw_gid) + os.setuid(pw_record.pw_uid) + + +def run_command(command, timeout = 30, poll_rate = 0.1, cwd = None, demote = False, is_daemon = False): + if not is_daemon: + assert timeout > 0, 'Timeout should be positive' + assert poll_rate > 0, 'Poll rate should be positive' + + preexec_fn = demote_func if demote else None + + try: # P2 + stdout_file = tempfile.TemporaryFile(bufsize = 0) + except: # P3 + stdout_file = tempfile.TemporaryFile(buffering = 0) + try: - tempfile.TemporaryFile(bufsize=0) - temp_params = {'bufsize': 0} - except: - tempfile.TemporaryFile(buffering=0) - temp_params = {'buffering': 0} - with tempfile.TemporaryFile(**temp_params) as stdout_file: - proc = subprocess.Popen(shlex.split(command), stdout = stdout_file, stderr = subprocess.STDOUT, cwd = cwd, close_fds = True, universal_newlines = True) + proc = subprocess.Popen(shlex.split(command), stdout = stdout_file, stderr = subprocess.STDOUT, cwd = cwd, + close_fds = True, universal_newlines = True, preexec_fn = preexec_fn) + if is_daemon: + return proc, stdout_file for i in range(int(timeout/poll_rate)): time.sleep(poll_rate) if proc.poll() is not None: # process stopped @@ -68,6 +81,9 @@ def run_command(command, timeout = 15, poll_rate = 0.1, cwd = None): return (errno.ETIMEDOUT, '%s\n\n...Timeout of %s second(s) is reached!' % (stdout_file.read(), timeout)) stdout_file.seek(0) return (proc.returncode, stdout_file.read()) + finally: + if not is_daemon: + stdout_file.close() def get_daemon_pid(): @@ -100,15 +116,37 @@ def start_daemon(): if is_running(): print(termstyle.red('Scapy server is already running')) return - server_path = os.path.join(pwd, 'automation', 'trex_control_plane', 'stl', 'services', 'scapy_server') - with tempfile.TemporaryFile() as stdout_file: - subprocess.Popen(shlex.split("taskset -c %s su -s /bin/bash -c '%s scapy_zmq_server.py -s %s' nobody" % (args.core, sys.executable, args.port)), - stdout = stdout_file, stderr = subprocess.STDOUT, cwd = server_path, close_fds = True, universal_newlines = True) - ret = progress(is_running, 'Starting Scapy server', 'Scapy server is started', 'Scapy server failed to run') + check_path = cur_dir + last_err_path = None + ret = -1 + while ret and check_path != '/': + ret, out = run_command("ls %s" % check_path, demote = True) if ret: - stdout_file.seek(0) - print('Output: %s' % stdout_file.read()) - sys.exit(1) + last_err_path = check_path + check_path = os.path.abspath(os.path.join(check_path, '..')) + if last_err_path: + msg = ''' +Error: current path is not readable by user "nobody" (starting at {path}). +Two possible solutions: + + 1. (Recommended) + Copy TRex to some public location (/tmp or /scratch, assuming it has proper permissions (chmod 777 etc.)) + + 2. (Not recommended) + Change permissions of current path. (Starting from directory {path}). + chmod 777 {path} -R +'''.format(path = last_err_path) + fail(msg) + + server_path = os.path.join(cur_dir, 'automation', 'trex_control_plane', 'stl', 'services', 'scapy_server') + cmd = 'taskset -c {core} {python} ./scapy_zmq_server.py -s {port}'.format(core = args.core, python = sys.executable, port = args.port) + proc, stdout_file = run_command(cmd, demote = True, is_daemon = True, cwd = server_path) + ret = progress(is_running, 'Starting Scapy server', 'Scapy server is started', 'Scapy server failed to run', fail_check = proc.poll) + if proc.poll(): + stdout_file.seek(0) + print('Output: %s' % stdout_file.read()) + stdout_file.close() + sys.exit(1) def restart_daemon(): @@ -124,14 +162,15 @@ def kill_daemon(): print(termstyle.red('Scapy server is NOT running')) return True run_command('kill %s' % pid) # usual kill - ret = progress(inv(is_running), 'Killing Scapy server', 'Scapy server is killed', 'failed') + ret = progress(inv(is_running), 'Killing Scapy server', 'Scapy server is killed', 'failed', timeout = 15) if not ret: return _, out = run_command('kill -9 %s' % pid) # unconditional kill - ret = progress(inv(is_running), 'Killing Scapy server with -9', 'Scapy server is killed', 'failed') + ret = progress(inv(is_running), 'Killing Scapy server with -9', 'Scapy server is killed', 'failed', timeout = 15) if ret: fail('Failed to kill Scapy server, even with -9. Please review manually.\nOutput: %s' % out) + ### Main ### if __name__ == '__main__': -- cgit 1.2.3-korg