You are not logged in.
I'm trying to use adguard-cli, and there's already an AUR package https://aur.archlinux.org/packages/adguard-cli-bin for it. However, this package breaks the auto_proxy functionality, so when you perform adguard-cli start, the auto proxy will always fail to start. To fix it, the binaries cannot be owned by root, unless you run it with sudo which at that point I think the implication is you apply adguard filtering system wide, which is not what I want to do. Therefore, I'm a bit confused on how to proceed. Should the PKGBUILD move the files to a user owned directory like .local/share or .local/bin? Should the PKGBUILD chown all the files to be user owned (Which as far as my reading goes, I found out, is a bad idea)? What's the best practice here?
For reference, the adguard-cli project has an install script in it. It installs itself into /opt, with every binary being owned by the user, and then symlinks one of the binaries into /usr/local/bin. Should I just follow this instead and make every file in /opt/adguard-cli to be user owned?
Offline
What "user"?
Nothing in /opt, let alone /usr should™ be owned by any one regular UID and the only way the file ownership can have impact on its runtime behavior is if it's suid' - which then most likely is a requirement (requires root permissions to function)
The AUR comment says the problem is a missing adguard-cli.sig, is that the only problem?
https://github.com/AdguardTeam/AdGuardC … 3021725142
PSA: do not EVER curl random urls into an shell. That's bash-roulette.
Download the script, inspect it locally and run it from there.
Offline
By "user", I mean a non-root user.
Also, the comment from the link I provided was from myself.
Yeah, I figured that's the best practice, but the upstream adguard install script installs binaries into /opt, where the installed directory is owned by the user who ran the install script. Unfortunately, installing the binaries into /opt (or any other directories) with root user ownership makes the auto_proxy functionality fail, as mentioned previously. There's 2 other binaries beside the main `adguard-cli` binary, which is `adguard_root_helper` and `certutils`. What the upstream install script does is create a symlink from /opt to /usr/local/bin (another thing I took note of, because as far as I know that's not best practice either) for `adguard-cli` binary only. It seems like `adguard-cli`, when being run with auto_proxy functionality enabled, runs `adguard_root_helper` internally. A snippet of the log when it fails is as follows:
```
05.05.2025 00:22:32.511983 INFO [44882] adguard_root_helper main: AdGuard CLI root helper starting with uid=0 euid=0
05.05.2025 00:22:32.512031 INFO [44882] adguard_root_helper set_suid_bit: Setting SUID bit on /opt/adguard-cli/adguard_root_helper
05.05.2025 00:22:32.512044 INFO [44882] adguard_root_helper set_suid_bit: SUID bit set successfully
05.05.2025 00:22:34.626984 WARN [44883] AGSslDomainFilter updateApps: The app list for the 'prestigecu.org' has been cleared by a rule without an app modifier
05.05.2025 00:22:34.626991 WARN [44883] AGSslDomainFilter updateApps: The app list for the 'papara.com' has been cleared by a rule without an app modifier
05.05.2025 00:22:34.627004 WARN [44883] AGSslDomainFilter updateApps: The app list for the 'e-tjanster.1177.se' has been cleared by a rule without an app modifier
05.05.2025 00:22:34.627024 WARN [44883] AGSslDomainFilter updateApps: The app list for the 'ssh.cloud.google.com' has been cleared by a rule without an app modifier
```
And yes, this is the only problem as far as I have observed.
And yes, I curled the script without running it directly, and inspected the script beforehand. Probably shouldn't have automated the execution on the PKGBUILD itself though.
Offline
install script installs binaries into /opt, where the installed directory is owned by the user who ran the install script
And what user can write stuff into /opt?
stat /optinstall script does is create a symlink from /opt to /usr/local/bin
Which is semi-fine, a package should write to /usr/bin (/usr/local/bin belongs to the local admin)
run with auto_proxy functionality enabled, runs `adguard_root_helper` internally
And I bet your right arm that adguard_root_helper has the SUID bit set?
(Your output also says so) - what user does that binary belong to (by default)?
I curled the script without running it directly
I mostly pointed that out for everybody else because I linked the relevant thread but wanted future readers to be aware that this is a really horrible pattern.
Long story short: adding the missing signatures (as does the installer script?) allows you to run adguard* w/o any further chowns to some random UID >= 1000 ("yours")?
=> add the missing signature. Leave the ownership alone.
---
If anything you might require some special "adguard" user/group, but I suspect owning anything to any UID that isn't /yours/ doesn't help anyway?
Offline
stat /opt
File: /opt
Size: 184 Blocks: 0 IO Block: 4096 directory
Device: 0,29 Inode: 350 Links: 1
Access: (0755/drwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2025-07-31 11:41:58.172832901 +0700
Modify: 2025-07-31 11:40:15.335963182 +0700
Change: 2025-07-31 11:40:15.335963182 +0700
Birth: 2024-10-29 15:05:13.445658975 +0700What the install script does is use sudo to mkdir and chown the directory /opt/adguard-cli for the sudo user.
create_dir() {
mkdir -p "$output_dir" 2>/dev/null
if [ $? -eq 1 ];
then
echo "Starting sudo to create directory '$output_dir'"
if sudo mkdir -p "$output_dir"; then
sudo chown -R "${SUDO_USER:-$USER}" "$output_dir"
log "'$output_dir' has been created and ownership has been set to '${SUDO_USER:-$USER}'"
else
error_exit "Failed to create '$output_dir' with sudo"
fi
else
log "'$output_dir' has been created"
fi
}After the installation with the upstream install script, /opt/adguard-cli looks like this:
drwxr-xr-x 1 mamba root 266 Jul 31 11:35 .
drwxr-xr-x 1 root root 184 Jul 31 11:34 ..
-rwxr-xr-x 1 mamba mamba 22966304 Apr 29 23:43 adguard-cli
-rw-r--r-- 1 mamba mamba 64 Apr 29 23:43 adguard-cli.sig
-rwxr-xr-x 1 mamba mamba 3882232 Apr 29 23:43 adguard_root_helper
-rw-r--r-- 1 mamba mamba 64 Apr 29 23:43 adguard_root_helper.sig
-rw-r--r-- 1 mamba mamba 2678 Apr 29 23:43 bash-completion.sh
-rwxr-xr-x 1 mamba mamba 4865856 Apr 29 23:43 certutil
-rw-r--r-- 1 mamba mamba 64 Apr 29 23:43 certutil.sig
-rw-r--r-- 1 mamba mamba 12727520 Apr 29 23:42 defaults.zip
-rwxr-xr-x 1 mamba mamba 3676 Apr 29 23:43 install_cert.shAnd after running
adguard-cli startwith auto_proxy on, the adguard_root_helper, like you said, gets its SUID bit set.
-rwsr-xr-x 1 root root 3882232 Apr 29 23:43 adguard_root_helperNothing else changed in /opt/adguard-cli after running the app.
By adding the missing signatures, do you mean adding the .sig files? I noticed the PKGBUILD from the existing AUR package does not add the .sig files, but I've tried adding them anyway and the problem still persists. Still not sure how to proceed here ![]()
Offline
This is completely whakko. You're sudo-installing something into a system path for a user-installation.
And apparently then that user has to invoke sudo in order to suid adguard_root_helper once they attempt to "adguard-cli start" as unprivileged user.
(What could have happened during the installation, but that's already 2nd degree madness here…)
The ownership in that directory will matter for
1. files that have the suid bit set (or guid…)
2. files that need to be written by the user and should™ reside somewhere in your $HOME (config files, caches ctec et pp)
I've tried adding them anyway and the problem still persists.
What does that installation look like (directory and permission-wise) and what is the actual, complete output when trying to start adguard-cli
Offline
I tried with the following PKGBUILD:
pkgname=adguard-cli
pkgver=1.0.16
pkgrel=1
pkgdesc="Surf the Web ad-free and safely. Shields up"
arch=('x86_64')
url="https://adguard.com/"
_pkgstatus=release
_file1="adguard-cli"
_file2="adguard-cli.sig"
_file3="adguard_root_helper"
_file4="adguard_root_helper.sig"
_file5="bash-completion.sh"
_file6="certutil"
_file7="certutil.sig"
_file8="defaults.zip"
_full_name="${_file1}-${pkgver}-linux-${arch}"
source=(
"https://github.com/AdguardTeam/AdGuardCLI/releases/download/v${pkgver}-${_pkgstatus}/${_full_name}.tar.gz"
)
sha256sums=('4486ac312793f4b8781b30bb312b48c1bd4c19eace244d2f59fa9fe3511f5c91')
package() {
cd "${srcdir}/${_full_name}"
mkdir -p "${pkgdir}/opt/${_file1}"
install -D "${_file1}" "${pkgdir}/opt/${_file1}/${_file1}"
install -D "${_file2}" "${pkgdir}/opt/${_file1}/${_file2}"
install -D "${_file3}" "${pkgdir}/opt/${_file1}/${_file3}"
install -D "${_file4}" "${pkgdir}/opt/${_file1}/${_file4}"
install -D "${_file5}" "${pkgdir}/opt/${_file1}/${_file5}"
install -D "${_file6}" "${pkgdir}/opt/${_file1}/${_file6}"
install -D "${_file7}" "${pkgdir}/opt/${_file1}/${_file7}"
install -D "${_file8}" "${pkgdir}/opt/${_file1}/${_file8}"
mkdir -p "${pkgdir}/usr/bin"
ln -sf "/opt/${_file1}/${_file1}" "${pkgdir}/usr/bin/${_file1}"
}And the /opt/adguard-cli looks like this (after running adguard-cli start, which is why the SUID bit is set)
total 43424
drwxr-xr-x 1 root root 236 Jul 31 14:02 .
drwxr-xr-x 1 root root 184 Jul 31 14:02 ..
-rwxr-xr-x 1 root root 22966408 Jul 31 14:02 adguard-cli
-rwxr-xr-x 1 root root 64 Jul 31 14:02 adguard-cli.sig
-rwsr-xr-x 1 root root 3882336 Jul 31 14:02 adguard_root_helper
-rwxr-xr-x 1 root root 64 Jul 31 14:02 adguard_root_helper.sig
-rwxr-xr-x 1 root root 2678 Jul 31 14:02 bash-completion.sh
-rwxr-xr-x 1 root root 4865952 Jul 31 14:02 certutil
-rwxr-xr-x 1 root root 64 Jul 31 14:02 certutil.sig
-rwxr-xr-x 1 root root 12727520 Jul 31 14:02 defaults.zipThere are 2 logs of interest as the output:
http://0x0.st/8R5T.js
http://0x0.st/8R5A.txt
Offline
http://0x0.st/8R5T.js logs what adguard is doing, there's a missing file, a bunch of deprecated stanzas, bogus regexps and duplicated entries but nothing looks critical?
http://0x0.st/8R5A.txt spans two days and thus probably multiple runs
29.07.2025 18:11:43.330872 WARN [135043] AdGuardCli process_cert: Failed to install certificate: Error at ag::CertificateManagerImpl::get_manual_install_script:98: Cert installer not exist
29.07.2025 18:11:43.331081 WARN [135043] AdGuardCli process_cert: Failed get manual install script: Cert installer not exist
29.07.2025 18:11:46.347440 INFO [135043] AdGuardCli ~AdGuardCli: Stop CLI App
29.07.2025 18:11:49.431253 INFO [135115] AdGuardCli AdGuardCli: Start AdGuard CLI App
29.07.2025 18:11:49.446695 INFO [135115] AdGuardCli is_root_helper_suid: Root helper check: owned_by_root=true, has_suid=false, is_executable=true
29.07.2025 18:11:50.924893 INFO [135115] AdGuardCli is_root_helper_suid: Root helper check: owned_by_root=true, has_suid=true, is_executable=truelooks suspicious, but is old and the last run
31.07.2025 16:32:45.374399 INFO [33927] AdGuardCli AdGuardCli: Start AdGuard CLI App
31.07.2025 16:32:45.385242 DEBUG [33927] SENTRY_WRAPPER operator(): using database path "/home/farel/.local/share/adguard-cli/.sentry-native"
31.07.2025 16:32:45.385312 DEBUG [33927] SENTRY_WRAPPER operator(): starting transport
31.07.2025 16:32:45.385370 DEBUG [33927] SENTRY_WRAPPER operator(): starting backend
31.07.2025 16:32:45.385408 DEBUG [33930] AGEventLoop run: Started event thread
31.07.2025 16:32:45.385439 DEBUG [33927] SENTRY_WRAPPER operator(): processing and pruning old runs
31.07.2025 16:32:45.396524 DEBUG [33927] AUTH get_app_status: Recently requested app status, returning cached value
31.07.2025 16:32:45.396552 DEBUG [33927] AdGuardCli get_app_state: Application status: APP_ACTIVE. Showing main menu looks uncritical.
What exactly doesn't work?
Offline
Huh, it seems like the logs got cut off.
adguard-cli start
01.08.2025 10:49:16.244746 DEBUG [49162] StandaloneProxyServer start: Automatic proxy server is listening at [::]:34473
01.08.2025 10:49:16.247201 DEBUG [49162] StandaloneProxyServer setup_auto_proxy: Setting up auto proxy
01.08.2025 10:49:16.244746 DEBUG [49162] StandaloneProxyServer start: Automatic proxy server is listening at [::]:34473
01.08.2025 10:49:16.247201 DEBUG [49162] StandaloneProxyServer setup_auto_proxy: Setting up auto proxy
01.08.2025 10:49:16.314164 DEBUG [49186] AGProxyServer periodicResolve: Next periodic resolve in 43200000ms
Failed to start proxy server: Failed to create auto proxyIt's one of those outputs that only shows the last 5 lines. I tried using
adguard-cli start > tempto capture the entire output but for some reason it also got cutoff in a lot of lines, but I guess its a bit better than nothing
http://0x0.st/87XF.txt
You can see at the bottom
[39;49mFailed to start proxy server: Failed to create auto proxyOffline
adguard-cli start > temp 2>&1otherwise you're not capturing stderr
strace -o /tmp/adguard-cli.strace -f -tt adguard-cli start
cat /tmp/adguard-cli.strace | curl -F 'file=@-' 0x0.stOffline
The captured stderr gives roughly the same output as before
http://0x0.st/87PT.txt
The strace output:
http://0x0.st/87Pc.txt
Offline
http://0x0.st/87Pc.txt is "451 Unavailable For Legal Reasons" ?
Wrong url?
Why is http://0x0.st/87PT.txt truncated and full of opening ansi sequences?
Is that actually a redirect or copypasted from a terminal?
Either way, if it doesn't produce more output at all we'll have to see the strace.
Offline
I could've sworn the link worked...
http://0x0.st/87fD.txt
This one SHOULD be working.
As for the truncated part, I don't really know. Like I mentioned before, the output on the terminal only shows the last 5 lines of the log, so I think those ANSI chars are responsible for that behavior. I don't know if I can change or disable that behavior. I ran
adguard-cli start > temp 2>&1Just like you recommended and then curled it to 0x0.st. The temp file itself is also truncated.
Offline
The link in #13 works for me and has almost 10k lines.
Disliking systemd intensely, but not satisfied with alternatives so focusing on taming systemd.
clean chroot building not flexible enough ?
Try clean chroot manager by graysky
Offline
Likewise - 10k LOC isn't too bad for a strace ![]()
4692 19:40:44.236932 execve("/opt/adguard-cli/adguard_root_helper", ["/opt/adguard-cli/adguard_root_he"..., "-v"], 0x7fdffeb53c60 /* 0 vars */ <unfinished ...>
4669 19:40:44.237015 <... clone resumed>) = 4692
4669 19:40:44.237027 close(74) = 0
4669 19:40:44.237047 read(73, "", 4) = 0
4669 19:40:44.237067 close(73) = 0
4692 19:40:44.237094 <... execve resumed>) = 0
4669 19:40:44.237099 rt_sigprocmask(SIG_SETMASK, [HUP INT TERM], NULL, 8) = 0
4669 19:40:44.237119 close(72) = 0
4669 19:40:44.237142 close(71 <unfinished ...>
4692 19:40:44.237155 arch_prctl(ARCH_SET_FS, 0x7bc300 <unfinished ...>
4669 19:40:44.237160 <... close resumed>) = 0
4692 19:40:44.237171 <... arch_prctl resumed>) = 0
4669 19:40:44.237175 fcntl(70, F_GETFL <unfinished ...>
4692 19:40:44.237186 set_tid_address(0x7bc3f0 <unfinished ...>
4669 19:40:44.237190 <... fcntl resumed>) = 0x2 (flags O_RDWR)
4692 19:40:44.237201 <... set_tid_address resumed>) = 4692
4669 19:40:44.237205 fcntl(70, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE <unfinished ...>
4692 19:40:44.237216 poll([{fd=0, events=0}, {fd=1, events=0}, {fd=2, events=0}], 3, 0 <unfinished ...>
4669 19:40:44.237222 <... fcntl resumed>) = 0
4692 19:40:44.237233 <... poll resumed>) = 0 (Timeout)
4669 19:40:44.237238 fcntl(70, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
4669 19:40:44.237258 epoll_ctl(66, EPOLL_CTL_ADD, 70, {events=EPOLLIN, data=0x46}) = 0
4669 19:40:44.237281 mmap(NULL, 143360, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fe004eb0000
4669 19:40:44.237304 mprotect(0x7fe004eb2000, 135168, PROT_READ|PROT_WRITE) = 0
4669 19:40:44.237327 rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [HUP INT TERM], 8) = 0
4669 19:40:44.237349 clone(child_stack=0x7fe004ed2798, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID|0x400000 <unfinished ...>
4692 19:40:44.237358 brk(NULL) = 0x3aa75000
4693 19:40:44.237390 rt_sigprocmask(SIG_SETMASK, [HUP INT TERM], <unfinished ...>
4669 19:40:44.237396 <... clone resumed>, parent_tid=[4693], tls=0x7fe004ed2b30, child_tidptr=0x1a0ec90) = 4693
4693 19:40:44.237404 <... rt_sigprocmask resumed>NULL, 8) = 0
4692 19:40:44.237409 brk(0x3aa77000 <unfinished ...>
4693 19:40:44.237415 epoll_pwait(66, <unfinished ...>
4669 19:40:44.237420 rt_sigprocmask(SIG_SETMASK, [HUP INT TERM], <unfinished ...>
4692 19:40:44.237426 <... brk resumed>) = 0x3aa77000
4669 19:40:44.237432 <... rt_sigprocmask resumed>NULL, 8) = 0
4692 19:40:44.237441 mmap(0x3aa75000, 4096, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0 <unfinished ...>
4669 19:40:44.237447 lseek(16, 0, SEEK_CUR) = 125049
4692 19:40:44.237461 <... mmap resumed>) = 0x3aa75000
4669 19:40:44.237467 gettid() = 4669
4692 19:40:44.237482 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
4669 19:40:44.237488 write(16, "02.08.2025 19:40:44.237461 DEBUG"..., 102 <unfinished ...>
4692 19:40:44.237500 <... mmap resumed>) = 0x7f4d26d36000
4669 19:40:44.237506 <... write resumed>) = 102
4669 19:40:44.237521 epoll_ctl(66, EPOLL_CTL_MOD, 70, {events=EPOLLIN|EPOLLOUT, data=0x46}) = 0
4693 19:40:44.237537 <... epoll_pwait resumed>[{events=EPOLLOUT, data=0x46}], 32, -1, NULL, 8) = 1
4669 19:40:44.237545 write(69, "\1\0\0\0\0\0\0\0", 8 <unfinished ...>
4693 19:40:44.237552 futex(0x7fdffc855c04, FUTEX_WAIT_PRIVATE, 2147483664, NULL <unfinished ...>
4692 19:40:44.237560 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
4669 19:40:44.237566 <... write resumed>) = 8
4692 19:40:44.237577 <... mmap resumed>) = 0x7f4d26d35000
4669 19:40:44.237581 futex(0x7fdffc855c04, FUTEX_WAKE_PRIVATE, 1 <unfinished ...>
4693 19:40:44.237593 <... futex resumed>) = 0
4669 19:40:44.237598 <... futex resumed>) = 1
4693 19:40:44.237604 epoll_ctl(66, EPOLL_CTL_MOD, 70, {events=EPOLLIN, data=0x46} <unfinished ...>
4669 19:40:44.237611 futex(0x7ffca798f954, FUTEX_WAIT_PRIVATE, 2, {tv_sec=29, tv_nsec=999999820} <unfinished ...>
4693 19:40:44.237618 <... epoll_ctl resumed>) = 0
4693 19:40:44.237630 epoll_ctl(66, EPOLL_CTL_MOD, 70, {events=EPOLLIN|EPOLLOUT, data=0x46}) = 0
4693 19:40:44.237649 epoll_pwait(66, [{events=EPOLLOUT, data=0x46}, {events=EPOLLIN, data=0x45}], 32, -1, NULL, 8) = 2
4692 19:40:44.237664 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
4693 19:40:44.237670 epoll_ctl(66, EPOLL_CTL_MOD, 70, {events=EPOLLIN, data=0x46}) = 0
4692 19:40:44.237684 <... mmap resumed>) = 0x7f4d26d34000
4693 19:40:44.237690 sendmsg(70, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0\0\0\r\n\10\n\2::\20\351\277\2\240\6\1", iov_len=17}], msg_iovlen=1, msg_controllen=0, msg_flags=0}, 0 <unfinished ...>
4692 19:40:44.237708 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0 <unfinished ...>
4693 19:40:44.237714 <... sendmsg resumed>) = 17
4693 19:40:44.237724 read(69, <unfinished ...>
4692 19:40:44.237729 <... mmap resumed>) = 0x7f4d26d33000
4693 19:40:44.237734 <... read resumed>"\1\0\0\0\0\0\0\0", 8) = 8
4693 19:40:44.237746 epoll_pwait(66, <unfinished ...>
4692 19:40:44.237754 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d32000
4692 19:40:44.237792 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d31000
4692 19:40:44.237831 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d30000
4692 19:40:44.237871 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d2f000
4692 19:40:44.237909 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d2e000
4692 19:40:44.237941 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d2d000
4692 19:40:44.237967 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d2c000
4692 19:40:44.237989 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d2b000
4692 19:40:44.238013 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d2a000
4692 19:40:44.238037 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d28000
4692 19:40:44.238060 brk(0x3aa78000) = 0x3aa78000
4692 19:40:44.238083 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d26000
4692 19:40:44.238117 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d25000
4692 19:40:44.238156 munmap(0x7f4d26d34000, 4096) = 0
4692 19:40:44.238182 munmap(0x7f4d26d33000, 4096) = 0
4692 19:40:44.238211 munmap(0x7f4d26d31000, 4096) = 0
4692 19:40:44.238234 munmap(0x7f4d26d2f000, 4096) = 0
4692 19:40:44.238258 munmap(0x7f4d26d2d000, 4096) = 0
4692 19:40:44.238282 munmap(0x7f4d26d2c000, 4096) = 0
4692 19:40:44.238306 munmap(0x7f4d26d32000, 4096) = 0
4692 19:40:44.238331 munmap(0x7f4d26d30000, 4096) = 0
4692 19:40:44.238352 munmap(0x7f4d26d2b000, 4096) = 0
4692 19:40:44.238374 munmap(0x7f4d26d2a000, 4096) = 0
4692 19:40:44.238542 mmap(NULL, 77824, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4d26d12000
4692 19:40:44.238576 rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x6afbb6}, {sa_handler=SIG_IGN, sa_mask=[], sa_flags=0}, 8) = 0
4692 19:40:44.238601 rt_sigprocmask(SIG_BLOCK, [HUP INT TERM], NULL, 8) = 0
4692 19:40:44.238664 open("/etc/localtime", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_CLOEXEC) = 6
4692 19:40:44.238694 fstat(6, {st_mode=S_IFREG|0644, st_size=383, ...}) = 0
4692 19:40:44.238717 mmap(NULL, 383, PROT_READ, MAP_SHARED, 6, 0) = 0x7f4d26d34000
4692 19:40:44.238741 close(6) = 0
4692 19:40:44.238765 gettid() = 4692
4692 19:40:44.238803 writev(2, [{iov_base="", iov_len=0}, {iov_base="02.08.2025 19:40:44.238657 DEBUG"..., iov_len=90}], 2) = 90
4692 19:40:44.238827 geteuid() = 1000
4692 19:40:44.238845 getuid() = 1000
4692 19:40:44.238864 gettid() = 4692
4692 19:40:44.238884 writev(2, [{iov_base="", iov_len=0}, {iov_base="02.08.2025 19:40:44.238859 INFO "..., iov_len=123}], 2) = 123
4692 19:40:44.238904 geteuid() = 1000
4692 19:40:44.238921 getuid() = 1000
4692 19:40:44.238938 geteuid() = 1000
4692 19:40:44.238956 rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [HUP INT TERM], 8) = 0
4692 19:40:44.238979 rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
4692 19:40:44.239000 setuid(1000) = 0
4692 19:40:44.239022 rt_sigprocmask(SIG_SETMASK, [HUP INT TERM], NULL, 8) = 0
4692 19:40:44.239041 getuid() = 1000
4692 19:40:44.239060 gettid() = 4692
4692 19:40:44.239078 writev(2, [{iov_base="", iov_len=0}, {iov_base="02.08.2025 19:40:44.239055 ERROR"..., iov_len=98}], 2) = 98
4692 19:40:44.239194 exit_group(1) = ?
4693 19:40:44.239311 <... epoll_pwait resumed>[{events=EPOLLIN|EPOLLERR|EPOLLHUP, data=0x46}], 32, -1, NULL, 8) = 1
4692 19:40:44.239317 +++ exited with 1 +++Only /opt/adguard-cli/adguard_root_helper errors out but that's expectable in a strace (because of the suid) and it's what's then causing
4669 19:40:44.240350 writev(1, [{iov_base="", iov_len=0}, {iov_base="Failed to start proxy server. Fa"..., iov_len=58}], 2 <unfinished ...>
4675 19:40:44.240358 writev(24, [{iov_base="\35\0\0\0\0\0\0\0\32\33Failed to create auto "..., iov_len=37}], 1 <unfinished ...>I assume you can run adguard-cli as root w/o problems?
(Because that's unfortunately the only context where you could strace w/o the SUID getting into the way)
mv /opt/adguard-cli/adguard_root_helper /opt/adguard-cli/adguard_root_helper.bin
printf '#!/bin/sh\nexec sudo /opt/adguard-cli/adguard_root_helper.bin\n' > /opt/adguard-cli/adguard_root_helperCan you now run adguard-cli ? (You'll ideally get asked for the sudo password)
Offline
It does work, but I'm a bit hesitant to use sudo with adguard-cli itself because that means the configs gets stored in ~/.local/share/adguard-cli, so running it with sudo means my config, license, etc is under /root/. My gut tells me that's probably not best practice? For my case specifically, since I'm the lone user of the system, it probably doesn't matter, but on the (extremely unlikely, I want to mention) niche case of someone having multiple users with multiple different licenses and configurations, sudo using the root config is a bit limiting.
Realistically though, I think this solution should be perfectly fine. Just want to get your thoughts as the experts in these matters about config files being stored in /root/.local/share/.
Last edited by thebrownmamba (2025-08-02 22:42:17)
Offline
That wasn't supposed to be a fix but to check where the problem is.
Apparently the suid leverage fails despite
-rwsr-xr-x 1 root root 3882336 Jul 31 14:02 adguard_root_helperAnd the /opt/adguard-cli looks like this (after running adguard-cli start, which is why the SUID bit is set)
How does running adguard-cli suid adguard_root_helper ? Do you run it as root at least once??
The github bug has
verify_signature: Signature file not found: /usr/share/adguard-cli/adguard-cli.sig and I guess (we're not gonna be able to strace it running suid…) what happens is that adguard_root_helper looks for that file if being suid's and that path is somewhat hardcoded at compilation time and is not where you put the file.
Did you
adguard-cli config set log_level debugand does that expose the failure point?
Offline
How does running adguard-cli suid adguard_root_helper ? Do you run it as root at least once??
If you run it with auto_proxy on, you'll get a message:
Automatic mode requires root helper to be set up, do you want to set it up? (yes/no): Which, when inputting yes, presumably runs
sudo adguard_root_helper -s internally which SUIDs itself.
The logs I've sent you were all with log_level set to debug.
While with the existing adguard-cli-bin AUR package the lack of the .sig file is also problematic (as even running adguard-cli start with sudo with this PKGBUILD won't work), I've been trying with my own PKGBUILD, which includes the .sig files like you can see from the ls output from my previous posts and this PKGBUILD can run successfully with sudo.
Offline
I don't know at all what the intention/implementation behind that signature is, but my gut feeling tells me that it's irrelevant when running as UID0 and otherwise used by the suid binary to verify itself (which sounds silly, but oh well)
And with that approach and the upstream bug and adguard_root_helper being precompiled the issue might simply be that it want's the signature in /usr/share/adguard-cli/adguard-cli.sig - not in /opt/adguard-cli/adguard-cli.sig
If you enable debugging for adguard-cli and try to run it w/ the otherwise failing suid helper: does it print any errors before failing?
Offline
But if the issue was the hard coded signature location, why would running sudo make it work? I personally think it's a red herring, which while it IS a relevant problem for the existing adguard-cli-bin AUR package, it's not the full picture of the problem.
Like I said, the previous logs I've sent you were all with debugging enabled. I've searched for ERROR strings but nothing popped up, and a quick skim doesn't really reveal any new information for me either. Here's a new log that thankfully doesn't get cut off like the previous logs by using
script -q -c "adguard-cli start" clean_output.logBut again, it's basically the same output as the previous logs I've sent you. For comparison and reference, here's the logs of a successful start by running sudo adguard-cli start:
http://0x0.st/8ha8.txt
One thing I noticed is that it seems running it with sudo does not invoke adguard_root_helper? But I'm not sure if it might be relevant for a solution
Last edited by thebrownmamba (2025-08-05 11:17:22)
Offline
why would running sudo make it work
Because sudo renders the suid irrelevant, geteuid() == getuid() and also
it seems running it with sudo does not invoke adguard_root_helper
For a cross-check, do you get more/other complaints when moving the signature file away?
Offline
Nope, nothing more. So is that the solution here? Making sure adguard_root_helper and/or adguard_root_helper.sig is in a specific location?
Offline
Maybe.
From the upstream bug you'd expect an error/warning if the signature is missing and the signature is missing.
Have you tried copying the signatures to /usr/share/adguard-cli/*.sig ?
Since we'll not be able to strace the suid binary, maybe
strings /opt/adguard-cli/* | grep sigcan give a hint.
Offline
With all the binaries belonging to root in /opt/adguard-cli, I copied all .sig files from /opt/adguard-cli to /usr/share/adguard-cli
[root@me adguard-cli]# ls -al /opt/adguard-cli/
total 43424
drwxr-xr-x 1 root root 236 Aug 5 18:00 .
drwxr-xr-x 1 root root 184 Aug 5 18:00 ..
-rwxr-xr-x 1 root root 22966408 Jul 31 14:02 adguard-cli
-rwxr-xr-x 1 root root 64 Jul 31 14:02 adguard-cli.sig
-rwsr-xr-x 1 root root 3882336 Jul 31 14:02 adguard_root_helper
-rwxr-xr-x 1 root root 64 Jul 31 14:02 adguard_root_helper.sig
-rwxr-xr-x 1 root root 2678 Jul 31 14:02 bash-completion.sh
-rwxr-xr-x 1 root root 4865952 Jul 31 14:02 certutil
-rwxr-xr-x 1 root root 64 Jul 31 14:02 certutil.sig
-rwxr-xr-x 1 root root 12727520 Jul 31 14:02 defaults.zip
[root@me adguard-cli]# ls -al /usr/share/adguard-cli/
total 12
drwxr-xr-x 1 root root 100 Aug 6 21:02 .
drwxr-xr-x 1 root root 3886 Aug 6 20:57 ..
-rwxr-xr-x 1 root root 64 Aug 6 21:01 adguard-cli.sig
-rwxr-xr-x 1 root root 64 Aug 6 20:57 adguard_root_helper.sig
-rwxr-xr-x 1 root root 64 Aug 6 21:02 certutil.sig
[root@me adguard-cli]#But still, running adguard-cli start without sudo fails. Result of
script -q -c "adguard-cli start" clean_output.log is as follows:
http://0x0.st/8hV7.txt
Result of
strings /opt/adguard-cli/* | grep sig is as follows:
http://0x0.st/8hVh.txt
Offline
The signature file doesn't show up in the strings output.
script -q -c "adguard-cli start" clean_output.log …
adguard-cli start |& tee adguard-cli.logBut at this point and since this is a binary only release you'll have to ask upstream what the fuck is wrong here.
Installing into /opt as the specific single regular user that's maybe gonna run this because that user will have to own random binaries in a system path is batshit crazy.
Ask them to explain their thought process that lead to this - and, in case avoiding script and assuming the other command leads to the same meaningless, cut-off output, maybe also to add some proper warning messages…
Offline