ntpd doesn't like ASLR on stable/12 post-r350672
Cy Schubert
Cy.Schubert at cschubert.com
Fri Sep 6 23:55:04 UTC 2019
In message <9b0c95de-2d0e-89b4-32e6-63ec5af729b4 at nwtime.org>, Harlan Stenn
writ
es:
> Hi folks,
>
> It's easy for us to customize the default value for DFLT_RLIMIT_STACK on
> a per-version and per-OS basis. We do this in the "configure" machinery.
>
> The defaults are expected to be "generally sane", and were likely chosen
> a relatively long time ago.
>
> What would you like the value(s) to be for what versions of FreeBSD?
>
> H
>
> On 9/5/2019 11:39 PM, Cy Schubert wrote:
> > In message <alpine.BSF.2.21.99999.352.1908242135380.6386 at enterprise.ximalas
> .
> > inf
> > o>, =?UTF-8?Q?Trond_Endrest=C3=B8l?= writes:
> >> Hi,
> >>
> >> I'm running stable/12 with ASLR enabled in /etc/sysctl.conf:
> >>
> >> kern.elf64.aslr.enable=1
> >> kern.elf64.aslr.pie_enable=1
> >> kern.elf32.aslr.enable=1
> >> kern.elf32.aslr.pie_enable=1
> >>
> >> After upgrading to anything after r350672, now at r351450, ntpd
> >> refuses to start at boot.
> >>
> >> Aug 24 21:25:42 <ntp.notice> HOSTNAME ntpd[5618]: ntpd 4.2.8p12-a (1): Sta
> rti
> >> ng
> >> Aug 24 21:25:43 <kern.info> HOSTNAME kernel: [406] pid 5619 (ntpd), jid 0,
> ui
> >> d 123: exited on signal 11
> >>
> >> Disabling ASLR, kern.elf64.aslr.enable=0, before starting ntpd
> >> manually is a workaround, but this is not viable in the long run.
> >>
> >> I tried changing command="/usr/sbin/${name}" to
> >> command="/usr/bin/proccontrol -m aslr -s disable /usr/sbin/${name}" in
> >> /etc/rc.d/ntpd, but that didn't go well.
> >
> > For now, until this can be solved, add this to your rc.conf:
> >
> > ntpd_prepend="/usr/bin/proccontrol -m aslr -s disable"
> >
> >>
> >> Running ntpd through gdb while ASLR was enabled, I narrowed it down to
> >> /usr/src/contrib/ntp/ntpd/ntpd.c:1001
> >>
> >> ntp_rlimit(RLIMIT_STACK, DFLT_RLIMIT_STACK * 4096, 4096, "4k");
> >>
> >> which calls /usr/src/contrib/ntp/ntpd/ntp_config.c:5211 and proceeds
> >> to /usr/src/contrib/ntp/ntpd/ntp_config.c:5254
> >>
> >> if (-1 == getrlimit(RLIMIT_STACK, &rl)) {
> >>
> >> Single stepping from this point gave me:
> >>
> >> ====
> >>
> >> (gdb) s
> >> _thr_rtld_set_flag (mask=1) at /usr/src/lib/libthr/thread/thr_rtld.c:171
> >> 171 {
> >> (gdb)
> >> 176 return (0);
> >> (gdb)
> >> _thr_rtld_rlock_acquire (lock=0x80180d200) at /usr/src/lib/libthr/thread/t
> hr_
> >> rtld.c:115
> >> 115 {
> >> (gdb)
> >> 120 curthread = _get_curthread();
> >> (gdb)
> >> _get_curthread () at /usr/src/lib/libthr/arch/amd64/include/pthread_md.h:9
> 7
> >> 97 return (TCB_GET64(tcb_thread));
> >> (gdb)
> >> _thr_rtld_rlock_acquire (lock=0x80180d200) at /usr/src/lib/libthr/thread/t
> hr_
> >> rtld.c:121
> >> 121 SAVE_ERRNO();
> >> (gdb)
> >> 124 THR_CRITICAL_ENTER(curthread);
> >> (gdb)
> >> _thr_rwlock_tryrdlock (rwlock=<optimized out>, flags=0) at /usr/src/lib/li
> bth
> >> r/thread/thr_umtx.h:192
> >> 192 (rwlock->rw_flags & URWLOCK_PREFER_READER) != 0)
> >> (gdb)
> >> 191 if ((flags & URWLOCK_PREFER_READER) != 0 ||
> >> (gdb)
> >> 197 while (!(state & wrflags)) {
> >> (gdb)
> >> 201 if (atomic_cmpset_acq_32(&rwlock->rw_state, state,
> st
> >> ate + 1))
> >> (gdb)
> >> atomic_cmpset_int (dst=<optimized out>, expect=<optimized out>, src=1) at
> /us
> >> r/obj/usr/src/amd64.amd64/tmp/usr/include/machine/atomic.h:220
> >> 220 ATOMIC_CMPSET(int);
> >> (gdb)
> >> _thr_rwlock_tryrdlock (rwlock=<optimized out>, flags=0) at /usr/src/lib/li
> bth
> >> r/thread/thr_umtx.h:201
> >> 201 if (atomic_cmpset_acq_32(&rwlock->rw_state, state,
> st
> >> ate + 1))
> >> (gdb)
> >> _thr_rtld_rlock_acquire (lock=0x80180d200) at /usr/src/lib/libthr/thread/t
> hr_
> >> rtld.c:127
> >> 127 curthread->rdlock_count++;
> >> (gdb)
> >> 128 RESTORE_ERRNO();
> >> (gdb)
> >> 129 }
> >> (gdb)
> >> _thr_rtld_clr_flag (mask=1) at /usr/src/lib/libthr/thread/thr_rtld.c:181
> >> 181 {
> >> (gdb)
> >> 182 return (0);
> >> (gdb)
> >> _thr_rtld_lock_release (lock=0x80180d200) at /usr/src/lib/libthr/thread/th
> r_r
> >> tld.c:150
> >> 150 {
> >> (gdb)
> >> _get_curthread () at /usr/src/lib/libthr/arch/amd64/include/pthread_md.h:9
> 7
> >> 97 return (TCB_GET64(tcb_thread));
> >> (gdb)
> >> _thr_rtld_lock_release (lock=0x80180d200) at /usr/src/lib/libthr/thread/th
> r_r
> >> tld.c:157
> >> 157 SAVE_ERRNO();
> >> (gdb)
> >> 160 state = l->lock.rw_state;
> >> (gdb)
> >> 161 if (_thr_rwlock_unlock(&l->lock) == 0) {
> >> (gdb)
> >> _thr_rwlock_unlock (rwlock=0x80180d200) at /usr/src/lib/libthr/thread/thr_
> umt
> >> x.h:249
> >> 249 state = rwlock->rw_state;
> >> (gdb)
> >> 250 if ((state & URWLOCK_WRITE_OWNER) != 0) {
> >> (gdb)
> >> 256 if (__predict_false(URWLOCK_READER_COUNT(s
> tat
> >> e) == 0))
> >> (gdb)
> >> 260 URWLOCK_READER_COUNT(state) == 1))
> >> {
> >> (gdb)
> >> 259 URWLOCK_READ_WAITERS)) != 0 &&
> >> (gdb)
> >> 262 state, state - 1))
> >> (gdb)
> >> 261 if (atomic_cmpset_rel_32(&rwlock->
> rw_
> >> state,
> >> (gdb)
> >> atomic_cmpset_int (dst=<optimized out>, expect=<optimized out>, src=0) at
> /us
> >> r/obj/usr/src/amd64.amd64/tmp/usr/include/machine/atomic.h:220
> >> 220 ATOMIC_CMPSET(int);
> >> (gdb)
> >> _thr_rwlock_unlock (rwlock=0x80180d200) at /usr/src/lib/libthr/thread/thr_
> umt
> >> x.h:261
> >> 261 if (atomic_cmpset_rel_32(&rwlock->
> rw_
> >> state,
> >> (gdb)
> >> _thr_rtld_lock_release (lock=<optimized out>) at /usr/src/lib/libthr/threa
> d/t
> >> hr_rtld.c:162
> >> 162 if ((state & URWLOCK_WRITE_OWNER) == 0)
> >> (gdb)
> >> 163 curthread->rdlock_count--;
> >> (gdb)
> >> 164 THR_CRITICAL_LEAVE(curthread);
> >> (gdb)
> >> _thr_ast (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_sig.c:2
> 71
> >> 271 if (!THR_IN_CRITICAL(curthread)) {
> >> (gdb)
> >> 272 check_deferred_signal(curthread);
> >> (gdb)
> >> check_deferred_signal (curthread=0x80864b000) at /usr/src/lib/libthr/threa
> d/t
> >> hr_sig.c:332
> >> 332 if (__predict_true(curthread->deferred_siginfo.si_signo ==
> 0
> >> ||
> >> (gdb)
> >> 351 }
> >> (gdb)
> >> _thr_ast (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_sig.c:2
> 73
> >> 273 check_suspend(curthread);
> >> (gdb)
> >> check_suspend (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_si
> g.c
> >> :358
> >> 358 if (__predict_true((curthread->flags &
> >> (gdb)
> >> 401 }
> >> (gdb)
> >> _thr_ast (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_sig.c:2
> 74
> >> 274 check_cancel(curthread, NULL);
> >> (gdb)
> >> check_cancel (curthread=0x80864b000, ucp=0x0) at /usr/src/lib/libthr/threa
> d/t
> >> hr_sig.c:283
> >> 283 if (__predict_true(!curthread->cancel_pending ||
> >> (gdb)
> >> _thr_ast (curthread=<optimized out>) at /usr/src/lib/libthr/thread/thr_sig
> .c:
> >> 276
> >> 276 }
> >> (gdb)
> >> _thr_rtld_lock_release (lock=<optimized out>) at /usr/src/lib/libthr/threa
> d/t
> >> hr_rtld.c:166
> >> 166 RESTORE_ERRNO();
> >> (gdb)
> >> 167 }
> >> (gdb)
> >> getrlimit () at getrlimit.S:3
> >> 3 RSYSCALL(getrlimit)
> >> (gdb)
> >> ntp_rlimit (rl_what=<optimized out>, rl_value=204800, rl_scale=<optimized
> out
> >>> , rl_sstr=<optimized out>) at /usr/src/contrib/ntp/ntpd/ntp_config.c:5257
> >> 5257 if (rl_value > rl.rlim_max) {
> >> (gdb)
> >> 5264 rl.rlim_cur = rl_value;
> >> (gdb)
> >> 5265 if (-1 == setrlimit(RLIMIT_STACK, &rl)) {
> >> (gdb)
> >> _thr_rtld_set_flag (mask=1) at /usr/src/lib/libthr/thread/thr_rtld.c:171
> >> 171 {
> >> (gdb)
> >> 176 return (0);
> >> (gdb)
> >> _thr_rtld_rlock_acquire (lock=0x80180d200) at /usr/src/lib/libthr/thread/t
> hr_
> >> rtld.c:115
> >> 115 {
> >> (gdb)
> >> 120 curthread = _get_curthread();
> >> (gdb)
> >> _get_curthread () at /usr/src/lib/libthr/arch/amd64/include/pthread_md.h:9
> 7
> >> 97 return (TCB_GET64(tcb_thread));
> >> (gdb)
> >> _thr_rtld_rlock_acquire (lock=0x80180d200) at /usr/src/lib/libthr/thread/t
> hr_
> >> rtld.c:121
> >> 121 SAVE_ERRNO();
> >> (gdb)
> >> 124 THR_CRITICAL_ENTER(curthread);
> >> (gdb)
> >> _thr_rwlock_tryrdlock (rwlock=<optimized out>, flags=0) at /usr/src/lib/li
> bth
> >> r/thread/thr_umtx.h:192
> >> 192 (rwlock->rw_flags & URWLOCK_PREFER_READER) != 0)
> >> (gdb)
> >> 191 if ((flags & URWLOCK_PREFER_READER) != 0 ||
> >> (gdb)
> >> 197 while (!(state & wrflags)) {
> >> (gdb)
> >> 201 if (atomic_cmpset_acq_32(&rwlock->rw_state, state,
> st
> >> ate + 1))
> >> (gdb)
> >> atomic_cmpset_int (dst=<optimized out>, expect=<optimized out>, src=1) at
> /us
> >> r/obj/usr/src/amd64.amd64/tmp/usr/include/machine/atomic.h:220
> >> 220 ATOMIC_CMPSET(int);
> >> (gdb)
> >> _thr_rwlock_tryrdlock (rwlock=<optimized out>, flags=0) at /usr/src/lib/li
> bth
> >> r/thread/thr_umtx.h:201
> >> 201 if (atomic_cmpset_acq_32(&rwlock->rw_state, state,
> st
> >> ate + 1))
> >> (gdb)
> >> _thr_rtld_rlock_acquire (lock=0x80180d200) at /usr/src/lib/libthr/thread/t
> hr_
> >> rtld.c:127
> >> 127 curthread->rdlock_count++;
> >> (gdb)
> >> 128 RESTORE_ERRNO();
> >> (gdb)
> >> 129 }
> >> (gdb)
> >> _thr_rtld_clr_flag (mask=1) at /usr/src/lib/libthr/thread/thr_rtld.c:181
> >> 181 {
> >> (gdb)
> >> 182 return (0);
> >> (gdb)
> >> _thr_rtld_lock_release (lock=0x80180d200) at /usr/src/lib/libthr/thread/th
> r_r
> >> tld.c:150
> >> 150 {
> >> (gdb)
> >> _get_curthread () at /usr/src/lib/libthr/arch/amd64/include/pthread_md.h:9
> 7
> >> 97 return (TCB_GET64(tcb_thread));
> >> (gdb)
> >> _thr_rtld_lock_release (lock=0x80180d200) at /usr/src/lib/libthr/thread/th
> r_r
> >> tld.c:157
> >> 157 SAVE_ERRNO();
> >> (gdb)
> >> 160 state = l->lock.rw_state;
> >> (gdb)
> >> 161 if (_thr_rwlock_unlock(&l->lock) == 0) {
> >> (gdb)
> >> _thr_rwlock_unlock (rwlock=0x80180d200) at /usr/src/lib/libthr/thread/thr_
> umt
> >> x.h:249
> >> 249 state = rwlock->rw_state;
> >> (gdb)
> >> 250 if ((state & URWLOCK_WRITE_OWNER) != 0) {
> >> (gdb)
> >> 256 if (__predict_false(URWLOCK_READER_COUNT(s
> tat
> >> e) == 0))
> >> (gdb)
> >> 260 URWLOCK_READER_COUNT(state) == 1)) {
> >> (gdb)
> >> 259 URWLOCK_READ_WAITERS)) != 0 &&
> >> (gdb)
> >> 262 state, state - 1))
> >> (gdb)
> >> 261 if (atomic_cmpset_rel_32(&rwlock->
> rw_
> >> state,
> >> (gdb)
> >> atomic_cmpset_int (dst=<optimized out>, expect=<optimized out>, src=0) at
> /us
> >> r/obj/usr/src/amd64.amd64/tmp/usr/include/machine/atomic.h:220
> >> 220 ATOMIC_CMPSET(int);
> >> (gdb)
> >> _thr_rwlock_unlock (rwlock=0x80180d200) at /usr/src/lib/libthr/thread/thr_
> umt
> >> x.h:261
> >> 261 if (atomic_cmpset_rel_32(&rwlock->
> rw_
> >> state,
> >> (gdb)
> >> _thr_rtld_lock_release (lock=<optimized out>) at /usr/src/lib/libthr/threa
> d/t
> >> hr_rtld.c:162
> >> 162 if ((state & URWLOCK_WRITE_OWNER) == 0)
> >> (gdb)
> >> 163 curthread->rdlock_count--;
> >> (gdb)
> >> 164 THR_CRITICAL_LEAVE(curthread);
> >> (gdb)
> >> _thr_ast (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_sig.c:2
> 71
> >> 271 if (!THR_IN_CRITICAL(curthread)) {
> >> (gdb)
> >> 272 check_deferred_signal(curthread);
> >> (gdb)
> >> check_deferred_signal (curthread=0x80864b000) at /usr/src/lib/libthr/threa
> d/t
> >> hr_sig.c:332
> >> 332 if
> >> (__predict_true(curthread->deferred_siginfo.si_signo == 0 ||
> >> (gdb)
> >> 351 }
> >> (gdb)
> >> _thr_ast (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_sig.c:2
> 73
> >> 273 check_suspend(curthread);
> >> (gdb)
> >> check_suspend (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_si
> g.c
> >> :358
> >> 358 if (__predict_true((curthread->flags &
> >> (gdb)
> >> 401 }
> >> (gdb)
> >> _thr_ast (curthread=0x80864b000) at /usr/src/lib/libthr/thread/thr_sig.c:2
> 74
> >> 274 check_cancel(curthread, NULL);
> >> (gdb)
> >> check_cancel (curthread=0x80864b000, ucp=0x0) at /usr/src/lib/libthr/threa
> d/t
> >> hr_sig.c:283
> >> 283 if (__predict_true(!curthread->cancel_pending ||
> >> (gdb)
> >> _thr_ast (curthread=<optimized out>) at /usr/src/lib/libthr/thread/thr_sig
> .c:
> >> 276
> >> 276 }
> >> (gdb)
> >> _thr_rtld_lock_release (lock=<optimized out>) at /usr/src/lib/libthr/threa
> d/t
> >> hr_rtld.c:166
> >> 166 RESTORE_ERRNO();
> >> (gdb)
> >> 167 }
> >> (gdb)
> >> setrlimit () at setrlimit.S:3
> >> 3 RSYSCALL(setrlimit)
> >> (gdb)
> >>
> >> Program received signal SIGSEGV, Segmentation fault.
> >> setrlimit () at setrlimit.S:3
> >> 3 RSYSCALL(setrlimit)
> >> (gdb)
> >>
> >> Program terminated with signal SIGSEGV, Segmentation fault.
> >> The program no longer exists.
> >> (gdb) q
> >>
> >> ====
> >>
> >> I'm sorry for the long post. Is there anything (else) I can do to
> >> further narrow it down?
> >
> > I've been able to confirm that kib@'s hunch regarding the gap is correct.
> >
> > Use the workaround until this can be solved.
> >
> >
A better workaround is, for people who wish to use ASLR, is to add this to
/etc/ntp.conf:
rlimit memlock 64
Currently the default is 32 MB. This sets the limit to 64.
--
Cheers,
Cy Schubert <Cy.Schubert at cschubert.com>
FreeBSD UNIX: <cy at FreeBSD.org> Web: http://www.FreeBSD.org
The need of the many outweighs the greed of the few.
More information about the freebsd-stable
mailing list