mirror of
https://github.com/ceph/ceph
synced 2025-02-22 10:37:15 +00:00
pybind: ceph_argparse: validate incorrectly formed targets
Prior to this patch find_cmd_target() would perform the following parsing for any given command: - check if it's a "tell" to a parseable CephName (i.e., ceph tell <type.id> ...) - if so, return <type>, <id> - check if it's a "tell" to a parseable PG id (e.g., ceph tell 0.4a) - if so, return 'pg', <pgid> - check if it's a "pg" command to a parseable PG id (e.g., ceph pg 0.4a) - if so, return 'pg', <pgid> - otherwise return 'mon', '' However, parsing of CephName and CephPgid is performed in a relaxed fashion, and tightening those checks requirements end up having nefarious effects on properly formed commands, whereas keeping them relaxed ends up having us returning 'mon','' in the end for a clearly malformed target (e.g., 'ceph tell foo ...'). This patch fixes this behavior by adding a new check: - if command is a "tell" and we were not able to parse either a CephName nor a PG id, then explicitely validate the target as a CephName (given we would be sending to a monitor anyway, we can just as well validate a 'tell' as a CephName). - if validation fails, we will propagate exceptions referring to the cause of the validation failure. Fixes: #10439 Signed-off-by: Joao Eduardo Luis <joao@redhat.com>
This commit is contained in:
parent
8618a5373e
commit
c4548f68ca
14
src/ceph.in
14
src/ceph.in
@ -425,7 +425,12 @@ def new_style_command(parsed_args, cmdargs, target, sigdict, inbuf, verbose):
|
|||||||
if interactive_input in ['q', 'quit', 'Q']:
|
if interactive_input in ['q', 'quit', 'Q']:
|
||||||
return 0, '', ''
|
return 0, '', ''
|
||||||
cmdargs = parse_cmdargs(interactive_input.split())[2]
|
cmdargs = parse_cmdargs(interactive_input.split())[2]
|
||||||
target = find_cmd_target(cmdargs)
|
try:
|
||||||
|
target = find_cmd_target(cmdargs)
|
||||||
|
except Exception as e:
|
||||||
|
print >> sys.stderr, \
|
||||||
|
'error handling command target: {0}'.format(e)
|
||||||
|
return 1
|
||||||
valid_dict = validate_command(sigdict, cmdargs, verbose)
|
valid_dict = validate_command(sigdict, cmdargs, verbose)
|
||||||
if valid_dict:
|
if valid_dict:
|
||||||
if parsed_args.output_format:
|
if parsed_args.output_format:
|
||||||
@ -753,7 +758,12 @@ def main():
|
|||||||
if parsed_args.status:
|
if parsed_args.status:
|
||||||
childargs.insert(0, 'status')
|
childargs.insert(0, 'status')
|
||||||
|
|
||||||
target = find_cmd_target(childargs)
|
try:
|
||||||
|
target = find_cmd_target(childargs)
|
||||||
|
except Exception as e:
|
||||||
|
print >> sys.stderr, \
|
||||||
|
'error handling command target: {0}'.format(e)
|
||||||
|
return 1
|
||||||
|
|
||||||
# Repulsive hack to handle tell: lop off 'tell' and target
|
# Repulsive hack to handle tell: lop off 'tell' and target
|
||||||
# and validate the rest of the command. 'target' is already
|
# and validate the rest of the command. 'target' is already
|
||||||
|
@ -1005,6 +1005,30 @@ def find_cmd_target(childargs):
|
|||||||
# pg doesn't need revalidation; the string is fine
|
# pg doesn't need revalidation; the string is fine
|
||||||
return 'pg', valid_dict['pgid']
|
return 'pg', valid_dict['pgid']
|
||||||
|
|
||||||
|
# If we reached this far it must mean that so far we've been unable to
|
||||||
|
# obtain a proper target from childargs. This may mean that we are not
|
||||||
|
# dealing with a 'tell' command, or that the specified target is invalid.
|
||||||
|
# If the latter, we likely were unable to catch it because we were not
|
||||||
|
# really looking for it: first we tried to parse a 'CephName' (osd, mon,
|
||||||
|
# mds, followed by and id); given our failure to parse, we tried to parse
|
||||||
|
# a 'CephPgid' instead (e.g., 0.4a). Considering we got this far though
|
||||||
|
# we were unable to do so.
|
||||||
|
#
|
||||||
|
# We will now check if this is a tell and, if so, forcefully validate the
|
||||||
|
# target as a 'CephName'. This must be so because otherwise we will end
|
||||||
|
# up sending garbage to a monitor, which is the default target when a
|
||||||
|
# target is not explicitly specified.
|
||||||
|
# e.g.,
|
||||||
|
# 'ceph status' -> target is any one monitor
|
||||||
|
# 'ceph tell mon.* status -> target is all monitors
|
||||||
|
# 'ceph tell foo status -> target is invalid!
|
||||||
|
if len(childargs) > 1 and childargs[0] == 'tell':
|
||||||
|
name = CephName()
|
||||||
|
# CephName.valid() raises on validation error; find_cmd_target()'s
|
||||||
|
# caller should handle them
|
||||||
|
name.valid(childargs[1])
|
||||||
|
return name.nametype, name.nameid
|
||||||
|
|
||||||
sig = parse_funcsig(['pg', {'name':'pgid', 'type':'CephPgid'}])
|
sig = parse_funcsig(['pg', {'name':'pgid', 'type':'CephPgid'}])
|
||||||
try:
|
try:
|
||||||
valid_dict = validate(childargs, sig, partial=True)
|
valid_dict = validate(childargs, sig, partial=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user