Allow non-superusers to debug their own functions and prevent them from setting global breakpoints. Fixes #2162

Based on a patch from Kit Yam Tse
This commit is contained in:
Murtuza Zabuawala 2017-06-27 16:58:07 -04:00 committed by Dave Page
parent 7f55412059
commit a9fa093d4b
2 changed files with 53 additions and 27 deletions

View File

@ -207,17 +207,6 @@ def init_function(node_type, sid, did, scid, fid, trid=None):
" and cannot be debugged."
)
else:
# If user is super user then we should check debugger library is loaded or not
if user['is_superuser']:
status_in, rid_pre = conn.execute_scalar("SHOW shared_preload_libraries")
if not status_in:
return internal_server_error(gettext("Could not fetch debugger plugin information."))
# Need to check if plugin is really loaded or not with "plugin_debugger" string
if "plugin_debugger" not in rid_pre:
ret_status = False
msg = gettext("The debugger plugin is not enabled. Please add the plugin to the shared_preload_libraries setting in the postgresql.conf file and restart the database server.")
status_in, rid_tar = conn.execute_scalar(
"SELECT count(*) FROM pg_proc WHERE proname = 'pldbg_get_target_info'")
if not status_in:
@ -385,6 +374,35 @@ def initialize_target(debug_type, sid, did, scid, func_id, tri_id=None):
if not status:
return internal_server_error(errormsg=str(msg))
user = manager.user_info
if debug_type == 'indirect':
# If user is super user then we should check debugger library is
# loaded or not
if not user['is_superuser']:
msg = gettext("You must be a superuser to set a global breakpoint "
"and perform indirect debugging.")
return internal_server_error(errormsg=msg)
else:
status_in, rid_pre = conn.execute_scalar(
"SHOW shared_preload_libraries"
)
if not status_in:
return internal_server_error(
gettext("Could not fetch debugger plugin information.")
)
# Need to check if plugin is really loaded or not with
# "plugin_debugger" string
if "plugin_debugger" not in rid_pre:
msg = gettext(
"The debugger plugin is not enabled. "
"Please add the plugin to the shared_preload_libraries "
"setting in the postgresql.conf file and restart the "
"database server for indirect debugging."
)
current_app.logger.debug(msg)
return internal_server_error(msg)
# Set the template path required to read the sql files
template_path = 'debugger/sql'

View File

@ -32,8 +32,8 @@ define([
name: 'global_debugger', node: 'function', module: this,
applies: ['object', 'context'], callback: 'check_func_debuggable',
category: gettext('Debugging'), priority: 10, label: gettext('Set breakpoint'),
data: {object: 'function'}, icon: 'fa fa-arrow-circle-right',
enable: 'can_debug'
data: {object: 'function', debug_type: 'indirect'},
icon: 'fa fa-arrow-circle-right', enable: 'can_debug'
},{
name: 'procedure_direct_debugger', node: 'procedure', module: this,
applies: ['object', 'context'], callback: 'get_function_information',
@ -44,20 +44,20 @@ define([
name: 'procedure_indirect_debugger', node: 'procedure', module: this,
applies: ['object', 'context'], callback: 'check_func_debuggable',
category: gettext('Debugging'), priority: 10, label: gettext('Set breakpoint'),
data: {object: 'procedure'}, icon: 'fa fa-arrow-circle-right',
enable: 'can_debug'
data: {object: 'procedure', debug_type: 'indirect'},
icon: 'fa fa-arrow-circle-right', enable: 'can_debug'
}, {
name: 'trigger_function_indirect_debugger', node: 'trigger_function', module: this,
applies: ['object', 'context'], callback: 'check_func_debuggable',
priority: 10, label: gettext('Set breakpoint'), category: gettext('Debugging'),
icon: 'fa fa-arrow-circle-right', data: {object:'trigger_function'},
enable: 'can_debug'
icon: 'fa fa-arrow-circle-right',
data: {object:'trigger_function', debug_type: 'indirect'}, enable: 'can_debug'
}, {
name: 'trigger_indirect_debugger', node: 'trigger', module: this,
applies: ['object', 'context'], callback: 'check_func_debuggable',
priority: 10, label: gettext('Set breakpoint'), category: gettext('Debugging'),
icon: 'fa fa-arrow-circle-right', data: {object:'trigger'},
enable: 'can_debug'
icon: 'fa fa-arrow-circle-right',
data: {object:'trigger', debug_type: 'indirect'}, enable: 'can_debug'
}, {
name: 'package_function_direct_debugger', node: 'edbfunc', module: this,
applies: ['object', 'context'], callback: 'get_function_information',
@ -68,8 +68,8 @@ define([
name: 'package_function_global_debugger', node: 'edbfunc', module: this,
applies: ['object', 'context'], callback: 'check_func_debuggable',
category: gettext('Debugging'), priority: 10, label: gettext('Set breakpoint'),
data: {object: 'edbfunc'}, icon: 'fa fa-arrow-circle-right',
enable: 'can_debug'
data: {object: 'edbfunc', debug_type: 'indirect'},
icon: 'fa fa-arrow-circle-right', enable: 'can_debug'
},{
name: 'package_procedure_direct_debugger', node: 'edbproc', module: this,
applies: ['object', 'context'], callback: 'get_function_information',
@ -80,8 +80,8 @@ define([
name: 'package_procedure_global_debugger', node: 'edbproc', module: this,
applies: ['object', 'context'], callback: 'check_func_debuggable',
category: gettext('Debugging'), priority: 10, label: gettext('Set breakpoint'),
data: {object: 'edbproc'}, icon: 'fa fa-arrow-circle-right',
enable: 'can_debug'
data: {object: 'edbproc', debug_type: 'indirect'},
icon: 'fa fa-arrow-circle-right', enable: 'can_debug'
}]);
// Create and load the new frame required for debugger panel
@ -121,6 +121,11 @@ define([
var treeInfo = node.getTreeNodeHierarchy.apply(node, [info]);
// For indirect debugging user must be super user
if(data && data.debug_type && data.debug_type == 'indirect'
&& !treeInfo.server.user.is_superuser)
return false;
// Must be a super user or object owner to create breakpoints of any kind
if (!(treeInfo.server.user.is_superuser || treeInfo.function.funcowner == treeInfo.server.user.name))
return false;
@ -269,10 +274,13 @@ define([
});
}
},
error: function(e) {
Alertify.alert(
'Debugger target initialization error'
);
error: function(xhr, status, error) {
try {
var err = $.parseJSON(xhr.responseText);
if (err.success == 0) {
Alertify.alert(err.errormsg);
}
} catch (e) {}
}
});
},