[Dnsmasq-discuss] dnsmasq-2.43rc3 available.
Simon Kelley
simon at thekelleys.org.uk
Thu Jul 10 13:23:44 BST 2008
Jean Wolter wrote:
> Simon Kelley <simon at thekelleys.org.uk> writes:
>
>> Patrick McLean wrote:
>>> On Linux 2.6.24 (Gentoo kernel, though I don't see why it wouldn't
>>> happen on other distros), starting this release with the user set to
>>> anything other than root fails with this message:
>>> dnsmasq: setting capabilities failed: Operation not permitted
>>>
>> I think I may have been guilty of answering the question I expected in
>> my last reply. Its valid if what you are talking about is running (as
>> root)
>>
>> dnsmasq --user <someuser>
>>
>> if you are actually starting dnsmasq as <someuser> (presumably
>> listening on a high port) then I can see that changing the capability
>> error from soft to hard is a problem. The solution is not to attempt
>> any of that stuff if the original process uid is non-zero.
>
> I tried dnsmaq *rc4
> - on 2.6.16.60
> - with SECURITY* disabled in its config
> zcat /proc/config.gz | grep SECURITY
> # CONFIG_SECURITY is not set
> - started with uid 0
> and it fails to drop priviledges. From an strace:
>
> 2302 capset(0x19980330, -1208317308,
> {CAP_SETUID|CAP_NET_ADMIN|CAP_NET_RAW, CAP_SETUID|CAP_NET_ADMIN|CAP_NET_RAW,
> CAP_SETUID|CAP_NET_ADMIN|CAP_NET_RAW}) = -1 EPERM (Operation not permitted)
> 2302 write(9, "\f\0\0\0\1\0\0\0", 8 <unfinished ...>
> 2298 <... read resumed> "\f\0\0\0\1\0\0\0", 8) = 8
> 2302 <... write resumed> ) = 8
> 2298 write(2, "\n", 1 <unfinished ...>
> 2302 _exit(0) = ?
> 2298 <... write resumed> ) = 1
> 2298 getpid() = 2298
> 2298 write(2, "dnsmasq: ", 9) = 9
> 2298 write(2, "setting capabilities failed: ", 29) = 29
> 2298 write(2, "Operation not permitted", 23) = 23
> 2298 write(2, "\n", 1) = 1
> # getuid/geteuid added for debugging purposes
> 2298 geteuid() = 0
> 2298 getuid() = 0
>
> It looks like this happens due to some uninitialized values (pid
> -1208317308); dnsmasq tries to set capabilities for arbitrary process
> ids. If I add the following, capset succeeds:
>
> --- dnsmasq-2.43rc4/src/dnsmasq.c.orig 2008-07-10 13:08:59.000000000 +0200
> +++ dnsmasq-2.43rc4/src/dnsmasq.c 2008-07-10 12:58:16.000000000 +0200
> @@ -383,6 +383,7 @@
> (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
>
> /* Tell kernel to not clear capabilities when dropping root */
> + hdr->pid = getpid();
> if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
> bad_capabilities = errno;
>
>
> 2334 capset(0x19980330, 2334, {CAP_SETUID|CAP_NET_ADMIN|CAP_NET_RAW,
> CAP_SETUID|CAP_NET_ADMIN|CAP_NET_RAW,
> CAP_SETUID|CAP_NET_ADMIN|CAP_NET_RAW}) = 0
> 2334 capset(0x19980330, 2334, {CAP_NET_ADMIN|CAP_NET_RAW,
> CAP_NET_ADMIN|CAP_NET_RAW, 0}) = 0
>
> dnsmasq starts and resolves names.
>
Kudos! Thanks for spotting that. The bug that causes this is more subtle
but more dangerous: hdr->pid is supposed to be zero, which means "the
current process", but the memset that clears hdr to zero got lost when
the code for determining the capability ABI version was moved to earlier
in the file. I also found that the memset zeroing the capability data
had args 2 and 3 swapped.
New rc soon......
Cheers,
Simon.
More information about the Dnsmasq-discuss
mailing list