core-agent-linux/qubesagent/vmexec.py
Pawel Marczewski 738548a8e4
Add qubes.VMExec call, for running a single command
With a VMExecGUI variant that waits for a session.

See QubesOS/qubes-issues#4850.
2020-01-24 18:44:45 +01:00

60 lines
1.4 KiB
Python

import sys
import os
import re
class DecodeError(ValueError):
pass
ESCAPE_RE = re.compile(br'--|-([A-F0-9]{2})')
def decode_part(part):
if not re.match(r'^[a-zA-Z0-9._-]*$', part):
raise DecodeError('illegal characters found')
part = part.encode('ascii')
# Check if no '-' remains outside of legal escape sequences.
if b'-' in ESCAPE_RE.sub(b'', part):
raise DecodeError("'-' can be used only in '-HH' or '--'")
def convert(m):
if m.group(0) == b'--':
return b'-'
num = int(m.group(1), 16)
return bytes([num])
return ESCAPE_RE.sub(convert, part)
def decode(arg):
'''
Decode the argument for executing. The format is as follows:
- individual parts are split by '+'
- bytes are escaped as '-HH' (where HH is hex code, capital letters only)
- literal '-' is encoded as '--'
- otherwise, only [a-zA-Z0-9._] are allowed
:param arg: argument, as a string
:returns: list of exec arguments (each as bytes)
'''
return [decode_part(part) for part in arg.split('+')]
def main(argv=sys.argv):
if len(argv) != 2:
print('This service requires exactly one argument', file=sys.stderr)
exit(1)
try:
command = decode(argv[1])
except DecodeError as e:
print('Decode error: {}'.format(e), file=sys.stderr)
exit(1)
os.execvp(command[0], command)
if __name__ == '__main__':
main()