dhcpcd icon indicating copy to clipboard operation
dhcpcd copied to clipboard

Failure on Pipeing dumplease from file

Open avlec opened this issue 1 year ago • 8 comments
trafficstars

When trying to run something like the following I only get a single line of text output when piping it into another program.

dhcpcd -4 --dumplease < /var/lib/dhcpcd/eth0.lease

outputs the following as expected

ip_address=10.0.1.6
subnet_cidr=16
network_number=10.0.0.0
subnet_mask=255.255.0.0
routers=10.0.0.1
domain_name_servers=10.0.0.1
host_name=farstar
domain_name=lan
broadcast_address=10.0.255.255
dhcp_lease_time=43200
dhcp_message_type=5
dhcp_server_identifier=10.0.0.1
dhcp_renewal_time=21600
dhcp_rebinding_time=37800

When trying to pipe the output to another program (or read from popen)

dhcpcd -4 --dumplease < /var/lib/dhcpcd/eth0.lease | less

Will display the following.

ip_address=10.0.0.y

Similarly if piped into wc it will display a count of words/chars in that line

Notable details is musl libc 1.2.4 and dhcpcd 10.0.6 (packaged together in a Yocto scarthgap build) I can provide more information if needed. I have straces but I doubt their utility

avlec avatar Oct 18 '24 23:10 avlec

I just ran this through the debugger to try to figure out what was happening. It seems that all the printf's for each line are called, and sanity checking the return value of one of the printf's was not in error.

I was wondering if it was related to the the resource limits but that seems to not be the case (e.g., skipping ps_dropprivs and ps_entersandbox) and that yielded no change in behaviour.

avlec avatar Oct 21 '24 17:10 avlec

Is it actually fetching the lease from the file? I noticed that if I backup a lease file, and then try to use stdin to load it, it prints the current lease, not the backup. Probably not directly related to the pipe issue, but just wanted to note it based on your example command. See #391

ColinMcInnes avatar Oct 25 '24 18:10 ColinMcInnes

Differences between my setup and your would be the version and I'm not running dhcpcd in managed mode. I am seeing the read call for stdin get hit and the contents match the file. I can even dumplease without any other dhcpcd process running (no other dhcpcd process is running before or after the call).

avlec avatar Oct 25 '24 23:10 avlec

When I run the same options as you it but with 10.0.10 says dhdpcd is not running and does not print the lease. Maybe something changed since 10.0.6

ColinMcInnes avatar Oct 26 '24 14:10 ColinMcInnes

As noted I'm also on Musl libc, and I saw all the print with each string being hit. I haven't a clue what could go wrong between there and the pipe. So maybe it's something there?

avlec avatar Oct 26 '24 16:10 avlec

You need to give the interface name - when dumping a lease from a file, as documented in the man page. See #285 for why we do this.

rsmarples avatar Oct 29 '24 09:10 rsmarples

I have tried using the - without any difference in behaviour. I haven't stepped through the application with the - provided as an option. But the strace is the same as without the -. When I was debugging without the - I saw all the printf calls being hit for each line in the leasefile, so the printf somehow isn't resulting in a writev call

...
read(0, "\2\1\6\0\1\265\5\20\377\377\0\0\n\220\1\n\n\220\1\n\n\220\0\1\0\0\0\0\0\2\331\20"..., 9230) = 311
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f09000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x76f08000
ioctl(1, TIOCGWINSZ, 0x7eaf99fc)        = -1 ENOTTY (Not a tty)
writev(1, [{iov_base="ip_address=10.144.1.10", iov_len=22}, {iov_base="\n", iov_len=1}], 2i)p _= 23a
ddress=10.144.1.10
munmap(0x76e76000, 69632)               = 0
munmap(0x76f08000, 4096)                = 0
munmap(0x76f0b000, 4096)                = 0
munmap(0x76f0c000, 8192)                = 0
close(-1)                               = -1 EBADF (Bad file descriptor)
munmap(0x76f0e000, 16384)               = 0
exit_group(0)                           = ?
+++ exited with 0 +++

When I run without pipeing from the ioctl on changes to the following which doesn't appear different with/without the -.

ioctl(1, TIOCGWINSZ, {ws_row=39, ws_col=195, ws_xpixel=0, ws_ypixel=0}) = 0
writev(1, [{iov_base="ip_address=10.144.1.10", iov_len=22}, {iov_base="\n", iov_len=1}], 2ip_address=10.144.1.10
) = 23
writev(1, [{iov_base="subnet_cidr=16", iov_len=14}, {iov_base="\n", iov_len=1}], 2subnet_cidr=16
) = 15
writev(1, [{iov_base="network_number=10.144.0.0", iov_len=25}, {iov_base="\n", iov_len=1}], 2network_number=10.144.0.0
) = 26
writev(1, [{iov_base="subnet_mask=255.255.0.0", iov_len=23}, {iov_base="\n", iov_len=1}], 2subnet_mask=255.255.0.0
) = 24
writev(1, [{iov_base="routers=10.144.0.1", iov_len=18}, {iov_base="\n", iov_len=1}], 2routers=10.144.0.1
) = 19
writev(1, [{iov_base="domain_name_servers=10.144.0.1", iov_len=30}, {iov_base="\n", iov_len=1}], 2domain_name_servers=10.144.0.1
) = 31
writev(1, [{iov_base="host_name=FAMBD0008105", iov_len=22}, {iov_base="\n", iov_len=1}], 2host_name=FAMBD0008105
) = 23
writev(1, [{iov_base="domain_name=lan", iov_len=15}, {iov_base="\n", iov_len=1}], 2domain_name=lan
) = 16
writev(1, [{iov_base="broadcast_address=10.144.255.255", iov_len=32}, {iov_base="\n", iov_len=1}], 2broadcast_address=10.144.255.255
) = 33
writev(1, [{iov_base="dhcp_lease_time=43200", iov_len=21}, {iov_base="\n", iov_len=1}], 2dhcp_lease_time=43200
) = 22
writev(1, [{iov_base="dhcp_message_type=5", iov_len=19}, {iov_base="\n", iov_len=1}], 2dhcp_message_type=5
) = 20
writev(1, [{iov_base="dhcp_server_identifier=10.144.0."..., iov_len=33}, {iov_base="\n", iov_len=1}], 2dhcp_server_identifier=10.144.0.1
) = 34
writev(1, [{iov_base="dhcp_renewal_time=19729", iov_len=23}, {iov_base="\n", iov_len=1}], 2dhcp_renewal_time=19729
) = 24
writev(1, [{iov_base="dhcp_rebinding_time=35929", iov_len=25}, {iov_base="\n", iov_len=1}], 2dhcp_rebinding_time=35929
) = 26
munmap(0x76ed5000, 69632)               = 0
munmap(0x76f67000, 4096)                = 0
munmap(0x76f6a000, 4096)                = 0
munmap(0x76f6b000, 8192)                = 0
close(-1)                               = -1 EBADF (Bad file descriptor)
munmap(0x76f6d000, 16384)               = 0
exit_group(0)                           = ?
+++ exited with 0 +++

avlec avatar Oct 29 '24 17:10 avlec

I cannot replicate this on alpine-3.20 which uses musl-1.2.5 The patch in #389 (now merged to master) might it fix for as well if you built with privsep. Can you test this please?

If it still fails, can you try ./configure --disable-privsep; make clean; make and try that? Thanks.

Note: The close(-1) at the end of the trace is due to closelog(3). openlog(3) was actually called earlier but no log entry was written. I've addressed this in fd2f66341644ba206b4604add2bc604403169406.

rsmarples avatar Oct 31 '24 10:10 rsmarples