'How to debug programs with "sudo" in VSCODE
I am trying to debug a program in VSCODE. The program needs to be launched as root or with "sudo" on Ubuntu. What's the best way to achieve this? An example launch configuration would be helpful. Thanks.
Solution 1:[1]
I have been in a similar situation recently- I have solved it by adding {"sudo": true} in launch.json file under .vscode directory.
just added the following line in .vscode>launch.json
{
"version": "0.2.0",
"configurations": [
{
"other..." : "configs...",
"request": "launch",
"console": "integratedTerminal",
"args": [
"${file}"
],
"sudo": true
}
]
}
VS code version I'm using is -
Version: 1.49.1 OS: Ubuntu 16.04 LTS, 64-bit
This appears to not work on all languages. For me it worked for python 3.x Other users reported it doesn't work for C/C++.
Solution 2:[2]
I did the following:
- create a script called "gdb" in e.g. my home directory, containing:
pkexec /usr/bin/gdb "$@" - make it executable
- modify the launch.json in VSCode to call the script (obviously change username accordingly) by adding "miDebuggerPath":
...
"externalConsole": false,
"miDebuggerPath": "/home/<username>/gdb",
"MIMode": "gdb",
...
- whilst debugging, use
topor such like to verify the process is running as root.
That should be enough.
Solution 3:[3]
My solution:
add /usr/bin/gdb to /etc/sudoers like here
add a executable file whose content is
sudo /usr/bin/gdb "$@"
set miDebuggerPath to the file
Solution 4:[4]
Do not know the way to make vscode to run sudo gdb. But you can sudo to run vscode so natually you can sudo gdb for debug.
sudo code . --user-data-dir='.'
Solution 5:[5]
As from the previous answers I had to use the method with a executable file in the home directory like: /home/youruser/gdbasroot
But I had to use the content:
sudo /usr/bin/gdb "$@"
instead of gdbk because I couldn't get gdbk to work without prompting for a password (which didnt work as its called by vscode remote debuger). I did it according this post (the upvoted and accepted answer):
https://askubuntu.com/questions/542397/change-default-user-for-authentication
When using sudo you can issue a sudo command in the vscode terminal and from then on you can use the "sudo debugger" without the password. Otherwise vscode gets prompted and can't handle it.
Greetings
Solution 6:[6]
I did the following:
- try what Jason did
- tired with endless annoying dialogue box for password
- write a python script to resolve that
launch.json:
...
"externalConsole": false,
"miDebuggerPath": "${workspaceFolder}/scripts/gdb_root.py",
"MIMode": "gdb",
...
gdb_root.py:
#!/usr/bin/python3
import os
import sys
import stat
import time
import json
import hashlib
from pathlib import Path
GRANT_EXPIRE_SEC = 2 * 60 * 60
TARGET_EXECUTABLE = '/usr/bin/gdb'
TMP_BIN_DIR = '/tmp/exec_as_root'
class ExecFailed(Exception):
pass
def instance_hash(argv):
command = ' '.join(argv)
return hashlib.md5(command.encode()).hexdigest()
def write_c_code(path, argv):
CODE_TEMPLATE = '''
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int test_mode = (argc > 1);
if (time(NULL) > (time_t)EXPIRE) {
char path[1024] = { 0 };
readlink("/proc/self/exe", path, sizeof(path));
unlink(path);
return !test_mode;
}
if (!test_mode)
execl(PARAMS, NULL);
return 0;
}'''
expire = time.time() + GRANT_EXPIRE_SEC
params = [argv[0]] + argv
params = json.dumps(params)[1:-1]
content = CODE_TEMPLATE \
.replace('EXPIRE', str(expire)) \
.replace('PARAMS', params)
with open(path, 'w') as f:
f.write(content)
def system(cmd):
is_ok = os.system(cmd) == 0
if not is_ok:
cmd_str = json.dumps(cmd)
summary = 'failed to execute:'
os.system(f'notify-send -- "{summary}" {cmd_str}')
raise ExecFailed()
def build_instance(instance, argv):
c_file = instance.with_suffix('.c')
write_c_code(c_file, argv)
compile_cmd = f'gcc -o {instance} {c_file}'
system(compile_cmd)
def did_grant_root(file):
fs = os.stat(file)
root_own = (fs.st_uid == 0)
uid_set = fs.st_mode & stat.S_ISUID
return root_own and uid_set
def grant_root(file):
setuid_cmd = f'chown root:root {file}; chmod 4111 {file}'
pkexec_cmd = f'pkexec bash -c "{setuid_cmd}"'
system(pkexec_cmd)
def main():
bin_dir = Path(TMP_BIN_DIR)
bin_dir.mkdir(exist_ok=True)
argv = [TARGET_EXECUTABLE] + sys.argv[1:]
instance = bin_dir / instance_hash(argv)
if instance.exists():
system(f'{instance} test')
if not instance.exists():
build_instance(instance, argv)
if not did_grant_root(instance):
grant_root(instance)
os.execv(instance, [instance.name])
if __name__ == '__main__':
try:
main()
except ExecFailed:
exit(1)
This is a portable solution, no effect to system, and do not forget: chmod +x scripts/gdb_root.py
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | bolov |
| Solution 2 | Den-Jason |
| Solution 3 | Yong-Hao Zou |
| Solution 4 | user7469511 |
| Solution 5 | Alex |
| Solution 6 |
