Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dhcpcd -U intermittently fails if stdin is connected to a pipe #285

Open
holmanb opened this issue Jan 18, 2024 · 2 comments · May be fixed by #289
Open

dhcpcd -U intermittently fails if stdin is connected to a pipe #285

holmanb opened this issue Jan 18, 2024 · 2 comments · May be fixed by #289

Comments

@holmanb
Copy link

holmanb commented Jan 18, 2024

System details:

# dhcpcd --version
dhcpcd 10.0.6
Copyright (c) 2006-2023 Roy Marples
Compiled in features: INET ARP ARPing IPv4LL INET6 DHCPv6 AUTH PRIVSEP
# uname -a
Linux SRU-worked-azure 6.6.0-1001-azure #1-Ubuntu SMP Fri Dec  1 11:34:03 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Dumping a lease file piped via stdin fails:

# cat /var/lib/dhcpcd/eth0.lease | dhcpcd --dumplease --ipv4only
dhcpcd is not running

But it doesn't with file redirection:

# dhcpcd --dumplease --ipv4only < /var/lib/dhcpcd/eth0.lease
ip_address=10.0.0.4
subnet_cidr=24
broadcast_address=10.0.0.255
network_number=10.0.0.0
server_name=IAD201121002027
subnet_mask=255.255.255.0
classless_static_routes=0.0.0.0/0 10.0.0.1 168.63.129.16/32 10.0.0.1 169.254.169.254/32 10.0.0.1
routers=10.0.0.1
domain_name_servers=168.63.129.16
domain_name=v1n0blf1qpvufijtbcm2fvnk3c.bx.internal.cloudapp.net
dhcp_lease_time=4294967295
dhcp_message_type=5
dhcp_server_identifier=168.63.129.16
dhcp_renewal_time=4294967295
dhcp_rebinding_time=4294967295

But it is inconsistent and sometimes works, even if dhcpcd isn't running:

# pgrep dhcpcd -a
# cat /var/lib/dhcpcd/eth0.lease | dhcpcd --dumplease --ipv4only
ip_address=10.0.0.4
subnet_cidr=24
broadcast_address=10.0.0.255
network_number=10.0.0.0
server_name=IAD201121002027
subnet_mask=255.255.255.0
classless_static_routes=0.0.0.0/0 10.0.0.1 168.63.129.16/32 10.0.0.1 169.254.169.254/32 10.0.0.1
routers=10.0.0.1
domain_name_servers=168.63.129.16
domain_name=v1n0blf1qpvufijtbcm2fvnk3c.bx.internal.cloudapp.net
dhcp_lease_time=4294967295
dhcp_message_type=5
dhcp_server_identifier=168.63.129.16
dhcp_renewal_time=4294967295
dhcp_rebinding_time=4294967295

an strace:

execve("/usr/sbin/dhcpcd", ["dhcpcd", "--dumplease", "--ipv4only"], 0x7fffd78fdc40 /* 20 vars */) = 0
brk(NULL)                               = 0x5c8869f85000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd9ea76e70) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7afc6e9e4000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=20577, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 20577, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7afc6e9de000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcrypto.so.3", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=5227352, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 5241760, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7afc6e400000
mmap(0x7afc6e4b3000, 3256320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb3000) = 0x7afc6e4b3000
mmap(0x7afc6e7ce000, 856064, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3ce000) = 0x7afc6e7ce000
mmap(0x7afc6e89f000, 385024, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x49e000) = 0x7afc6e89f000
mmap(0x7afc6e8fd000, 11168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7afc6e8fd000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\202\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2104632, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2149776, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7afc6e000000
mmap(0x7afc6e026000, 1568768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x7afc6e026000
mmap(0x7afc6e1a5000, 348160, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a5000) = 0x7afc6e1a5000
mmap(0x7afc6e1fa000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1f9000) = 0x7afc6e1fa000
mmap(0x7afc6e200000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7afc6e200000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7afc6e9db000
arch_prctl(ARCH_SET_FS, 0x7afc6e9db740) = 0
set_tid_address(0x7afc6e9dba10)         = 18051
set_robust_list(0x7afc6e9dba20, 24)     = 0
rseq(0x7afc6e9dc060, 0x20, 0, 0x53053053) = 0
mprotect(0x7afc6e1fa000, 16384, PROT_READ) = 0
mprotect(0x7afc6e89f000, 372736, PROT_READ) = 0
mprotect(0x5c8869337000, 8192, PROT_READ) = 0
mprotect(0x7afc6ea1b000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7afc6e9de000, 20577)           = 0
getrandom("\x82\xe9\x7d\x12\x36\x6e\x8e\xc4", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x5c8869f85000
brk(0x5c8869fa6000)                     = 0x5c8869fa6000
fcntl(0, F_GETFD)                       = 0
fcntl(1, F_GETFD)                       = 0
fcntl(2, F_GETFD)                       = 0
openat(AT_FDCWD, "/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114
lseek(3, -60, SEEK_CUR)                 = 54
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60
close(3)                                = 0
readlink("/proc/self/exe", "/usr/sbin/dhcpcd", 4097) = 16
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
close(3)                                = 0
socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
close(3)                                = 0
openat(AT_FDCWD, "/etc/dhcpcd.conf", O_RDONLY) = 3
read(3, "# A sample configuration for dhc"..., 65536) = 1429
close(3)                                = 0
newfstatat(AT_FDCWD, "/etc/dhcpcd.conf", {st_mode=S_IFREG|0644, st_size=1429, ...}, 0) = 0
chdir("/")                              = 0
rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7afc6e042900}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT USR1 USR2 ALRM TERM CHLD], [], 8) = 0
rt_sigaction(SIGTERM, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
rt_sigaction(SIGALRM, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
rt_sigaction(SIGUSR1, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
rt_sigaction(SIGUSR2, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
rt_sigaction(SIGCHLD, {sa_handler=0x5c88692e5080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7afc6e042900}, NULL, 8) = 0
futex(0x7afc6e8fd1e4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd1e0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd1dc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd5c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
brk(0x5c8869fc7000)                     = 0x5c8869fc7000
futex(0x7afc6e8fd1d4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd1d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fce10, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd0c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fcde8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd1d8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
openat(AT_FDCWD, "/usr/lib/ssl/openssl.cnf", O_RDONLY) = 3
futex(0x7afc6e8fcb10, FUTEX_WAKE_PRIVATE, 2147483647) = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=12324, ...}, AT_EMPTY_PATH) = 0
read(3, "#\n# OpenSSL example configuratio"..., 4096) = 4096
read(3, "d attributes must be the same, a"..., 4096) = 4096
read(3, "coding of an extension: beware e"..., 4096) = 4096
read(3, " = $insta::certout # insta.cert."..., 4096) = 36
read(3, "", 4096)                       = 0
close(3)                                = 0
futex(0x7afc6e8fcd64, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fcda4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd1c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fcd6c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x7afc6e8fd1cc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
newfstatat(AT_FDCWD, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=526, ...}, 0) = 0
newfstatat(AT_FDCWD, "/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=526, ...}, AT_EMPTY_PATH) = 0
read(3, "# /etc/nsswitch.conf\n#\n# Example"..., 4096) = 526
read(3, "", 4096)                       = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=526, ...}, AT_EMPTY_PATH) = 0
close(3)                                = 0
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=1837, ...}, AT_EMPTY_PATH) = 0
lseek(3, 0, SEEK_SET)                   = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1837
close(3)                                = 0
newfstatat(AT_FDCWD, "/usr/lib/dhcpcd", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
ioctl(0, FIONREAD, [370])               = 0
chroot("/usr/lib/dhcpcd")               = 0
chdir("/")                              = 0
setgroups(1, [65534])                   = 0
setgid(65534)                           = 0
setuid(100)                             = 0
ioctl(2, TCGETS, 0x7ffd9ea768a0)        = -1 ENOTTY (Inappropriate ioctl for device)
prlimit64(0, RLIMIT_NPROC, {rlim_cur=0, rlim_max=0}, NULL) = 0
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)  = 0
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=136, filter=0x5c886933b060}) = 0
read(0, "\2\1\6\0F\255XZ\0\0\200\0\0\0\0\0\n\0\0\4\250?\201\20\250?\201\20\0\"H/"..., 9230) = 370
newfstatat(1, "", {st_mode=S_IFIFO|0600, st_size=0, ...}, AT_EMPTY_PATH) = 0
exit_group(0)                           = ?
+++ exited with 0 +++

I see that privsep might be hiding the bigger picture, so I run the same under
strace --follow-forks --output-separately --output=./strace.log, and I see:

strace.log:

sandbox: seccomp
reading standard input
sandbox: seccomp
reading standard input

and
strace.log.18379

execve("/usr/sbin/dhcpcd", ["dhcpcd", "--dumplease", "--ipv4only", "--debug"], 0x7ffdf30b0a20 /* 20 vars */) = 0
brk(NULL)                               = 0x5dcd6b42e000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd556f7ac0) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x74d42f005000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=20577, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 20577, PROT_READ, MAP_PRIVATE, 3, 0) = 0x74d42efff000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libcrypto.so.3", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=5227352, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 5241760, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x74d42ea00000
mmap(0x74d42eab3000, 3256320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb3000) = 0x74d42eab3000
mmap(0x74d42edce000, 856064, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3ce000) = 0x74d42edce000
mmap(0x74d42ee9f000, 385024, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x49e000) = 0x74d42ee9f000
mmap(0x74d42eefd000, 11168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x74d42eefd000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\202\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=2104632, ...}, AT_EMPTY_PATH) = 0
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
mmap(NULL, 2149776, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x74d42e600000
mmap(0x74d42e626000, 1568768, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x26000) = 0x74d42e626000
mmap(0x74d42e7a5000, 348160, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a5000) = 0x74d42e7a5000
mmap(0x74d42e7fa000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1f9000) = 0x74d42e7fa000
mmap(0x74d42e800000, 52624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x74d42e800000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x74d42effc000
arch_prctl(ARCH_SET_FS, 0x74d42effc740) = 0
set_tid_address(0x74d42effca10)         = 18379
set_robust_list(0x74d42effca20, 24)     = 0
rseq(0x74d42effd060, 0x20, 0, 0x53053053) = 0
mprotect(0x74d42e7fa000, 16384, PROT_READ) = 0
mprotect(0x74d42ee9f000, 372736, PROT_READ) = 0
mprotect(0x5dcd698c8000, 8192, PROT_READ) = 0
mprotect(0x74d42f03c000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x74d42efff000, 20577)           = 0
getrandom("\x55\x0e\xba\x30\xde\x7c\x07\x40", 8, GRND_NONBLOCK) = 8
brk(NULL)                               = 0x5dcd6b42e000
brk(0x5dcd6b44f000)                     = 0x5dcd6b44f000
fcntl(0, F_GETFD)                       = 0
fcntl(1, F_GETFD)                       = 0
fcntl(2, F_GETFD)                       = 0
openat(AT_FDCWD, "/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114
lseek(3, -60, SEEK_CUR)                 = 54
read(3, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60
close(3)                                = 0
readlink("/proc/self/exe", "/usr/sbin/dhcpcd", 4097) = 16
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
close(3)                                = 0
socket(AF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
close(3)                                = 0
openat(AT_FDCWD, "/etc/dhcpcd.conf", O_RDONLY) = 3
read(3, "# A sample configuration for dhc"..., 65536) = 1429
close(3)                                = 0
newfstatat(AT_FDCWD, "/etc/dhcpcd.conf", {st_mode=S_IFREG|0644, st_size=1429, ...}, 0) = 0
chdir("/")                              = 0
rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x74d42e642900}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [HUP INT USR1 USR2 ALRM TERM CHLD], [], 8) = 0
rt_sigaction(SIGTERM, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
rt_sigaction(SIGALRM, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
rt_sigaction(SIGHUP, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
rt_sigaction(SIGUSR1, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
rt_sigaction(SIGUSR2, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
rt_sigaction(SIGCHLD, {sa_handler=0x5dcd69876080, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x74d42e642900}, NULL, 8) = 0
futex(0x74d42eefd1e4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd1e0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd1dc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd5c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
brk(0x5dcd6b470000)                     = 0x5dcd6b470000
futex(0x74d42eefd1d4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd1d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefce10, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd0c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefcde8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd1d8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
openat(AT_FDCWD, "/usr/lib/ssl/openssl.cnf", O_RDONLY) = 3
futex(0x74d42eefcb10, FUTEX_WAKE_PRIVATE, 2147483647) = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=12324, ...}, AT_EMPTY_PATH) = 0
read(3, "#\n# OpenSSL example configuratio"..., 4096) = 4096
read(3, "d attributes must be the same, a"..., 4096) = 4096
read(3, "coding of an extension: beware e"..., 4096) = 4096
read(3, " = $insta::certout # insta.cert."..., 4096) = 36
read(3, "", 4096)                       = 0
close(3)                                = 0
futex(0x74d42eefcd64, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefcda4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd1c0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefcd6c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
futex(0x74d42eefd1cc, FUTEX_WAKE_PRIVATE, 2147483647) = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
newfstatat(AT_FDCWD, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=526, ...}, 0) = 0
newfstatat(AT_FDCWD, "/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=526, ...}, AT_EMPTY_PATH) = 0
read(3, "# /etc/nsswitch.conf\n#\n# Example"..., 4096) = 526
read(3, "", 4096)                       = 0
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=526, ...}, AT_EMPTY_PATH) = 0
close(3)                                = 0
openat(AT_FDCWD, "/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=1837, ...}, AT_EMPTY_PATH) = 0
lseek(3, 0, SEEK_SET)                   = 0
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1837
close(3)                                = 0
newfstatat(AT_FDCWD, "/usr/lib/dhcpcd", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
ioctl(0, FIONREAD, [370])               = 0
chroot("/usr/lib/dhcpcd")               = 0
chdir("/")                              = 0
setgroups(1, [65534])                   = 0
setgid(65534)                           = 0
setuid(100)                             = 0
ioctl(2, TCGETS, 0x7ffd556f74f0)        = -1 ENOTTY (Inappropriate ioctl for device)
prlimit64(0, RLIMIT_NPROC, {rlim_cur=0, rlim_max=0}, NULL) = 0
prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)  = 0
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=136, filter=0x5dcd698cc060}) = 0
write(2, "sandbox: seccomp\n", 17)      = 17
write(2, "reading standard input\n", 23) = 23
read(0, "\2\1\6\0>1\23\205\0\0\200\0\0\0\0\0\n\0\0\4\250?\201\20\250?\201\20\0\"H/"..., 9230) = 370
newfstatat(1, "", {st_mode=S_IFIFO|0600, st_size=0, ...}, AT_EMPTY_PATH) = 0
exit_group(0)                           = ?
+++ exited with 0 +++
@holmanb
Copy link
Author

holmanb commented Jan 18, 2024

Digging further, it seems like if the lease file is still in page cache, the cat method succeeds (repeated calls succeed, a "cold" call usually fails). I'm still testing, but right now this ioctl call looks pretty suspicious. What if dhcpcd reaches this point in the code before cat (or some other program) has started writing to stdout?

@holmanb
Copy link
Author

holmanb commented Jan 19, 2024

this ioctl call looks pretty suspicious. What if dhcpcd reaches this point in the code before cat (or some other program) has started writing to stdout?

Introducing a sleep before piping to dhcpcd appears to make dumplease consistently fail:

$ (sleep 0.1; sudo cat /var/lib/dhcpcd/enp24s0.lease) | dhcpcd --dumplease -4
dhcpcd is not running

There is a secondary failure path that is possible for --dumplease callers that are using unbuffered output or small buffer sizes. This can be reproduced via:

# (dd if=/var/lib/dhcpcd/enp24s0.lease bs=1 count=1 2>/dev/null; sleep 1; dd if=/var/lib/dhcpcd/enp24s0.lease skip=1 ibs=1 2>/dev/null) | dhcpcd --dumplease -4
: read_lease: truncated lease
read_lease: Success

This is possible due to dhcpcd issuing a single read() on stdin as soon as data is available. This secondary failure path would be harder to solve, and I don't think that it actually affects my use case, but seems worth mentioning (let me know if you want that filed separately).

holmanb added a commit to holmanb/dhcpcd that referenced this issue Jan 20, 2024
Checking if data exists in the stdin buffer via an ioctl is
unreliable. Allow a user to pass '-' to force stdin parsing.
This provides a fix that will allow "no interfaces" to still
mean "dump all interfaces".

Fixes NetworkConfiguration#285
holmanb added a commit to holmanb/dhcpcd that referenced this issue Jan 20, 2024
Previous code used the non-existance of data in the input buffer to
determine whether to attempt parsing from stdin. This is racy, so
`dhcpcd -U < /path/to/lease` will sometimes fail:

  # dhcpcd --dumplease --ipv4only < /var/lib/dhcpcd/<iface>.lease
  dhcpcd is not running

 The fix uses the (non-)existance of an interface argument to indicate
 that dhcpcd should wait for data to arrive on stdin.

Fixes NetworkConfiguration#285
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant