NetBSD Problem Report #60737

From www@netbsd.org  Thu Sep 17 01:15:44 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits)
	 client-signature RSA-PSS (2048 bits))
	(Client CN "mail.netbsd.org", Issuer "YR1" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id EE2051A923B
	for <gnats-bugs@gnats.NetBSD.org>; Thu, 17 Sep 2026 01:15:43 +0000 (UTC)
Message-Id: <20260917011542.840471A923E@mollari.NetBSD.org>
Date: Thu, 17 Sep 2026 01:15:42 +0000 (UTC)
From: david@gutteridge.ca
Reply-To: david@gutteridge.ca
To: gnats-bugs@NetBSD.org
Subject: At securelevel 2, root can still set the clock backwards, contrary to what securelevel(9) states
X-Send-Pr-Version: www-1.0
X-From4GNATS: "david@gutteridge.ca via gnats" <gnats-admin@NetBSD.org>

>Number:         60737
>Category:       kern
>Synopsis:       At securelevel 2, root can still set the clock backwards, contrary to what securelevel(9) states
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          analyzed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Sep 17 01:20:00 +0000 2026
>Closed-Date:    
>Last-Modified:  Thu Sep 17 01:59:02 +0000 2026
>Originator:     David H. Gutteridge
>Release:        HEAD
>Organization:
TNF
>Environment:
NetBSD arm64 11.99.8 NetBSD 11.99.8 (GENERIC64) #0: Mon Sep  7 08:02:15 UTC 2026  mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC64 evbarm
>Description:
Simply put, securelevel(9) states that under securelevel 2 "The system
clock may not be set backwards or close to overflow." I read this to
mean just that, that one then cannot use date(1) or any other utility
to set the time backwards.

Evidently this is not true, e.g.,

arm64$ uname -a
NetBSD arm64 11.99.8 NetBSD 11.99.8 (GENERIC64) #0: Mon Sep  7 08:02:15 UTC 2026  mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC64 evbarm
arm64$ sysctl -a | grep securelevel
kern.securelevel = 2
security.models.bsd44.securelevel = 2
security.models.securelevel.name = Traditional NetBSD: Securelevel
security.models.securelevel.securelevel = 2
[...]
arm64# date
Wed Sep 16 16:47:35 UTC 2026
arm64# date 1532.00
Wed Sep 16 15:32:00 UTC 2026
arm64# date
Wed Sep 16 15:32:02 UTC 2026
arm64# rdate -4 time.nist.gov
Wed Sep 16 16:48:06 2026
arm64# date
Wed Sep 16 16:48:07 UTC 2026

Either the intended implementation is broken, or the documentation needs
more detail to explain just what is meant. (I'm guessing it's broken.
I haven't looked at the code, yet. I gather we don't have test cases
for expected behavioural differences at different securelevel settings,
too.)

>How-To-Repeat:
As above.
>Fix:
Not analyzed.

>Release-Note:

>Audit-Trail:

State-Changed-From-To: open->analyzed
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Thu, 17 Sep 2026 01:58:44 +0000
State-Changed-Why:
This is inadvertently allowed by the /dev/clockctl path, which is meant
to allow adjusting the clock even if uid != 0 -- but also allows clock
shenanigans even if securelevel > 1.

The reason this happens is that the two checks are combined into one
kauth(9) query, and in an attempt to bypass the uid != 0 check for
clockctl, the logic also bypasses the securelevel > 1 check:

    226 	if (check_kauth && kauth_authorize_system(kauth_cred_get(),
    227 	    KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, __UNCONST(ts),
    228 	    &delta, KAUTH_ARG(check_kauth ? false : true)) != 0) {
    229 		return SET_ERROR(EPERM);

https://nxr.NetBSD.org/xref/src/sys/kern/kern_time.c?r=1.232#226

Why the KAUTH_ARG(check_kauth ? false : true) argument is passed
through here is unclear to me; in context, check_kauth is _always_ true
at that point, and...none of the secmodels use the parameter anyway.
Perhaps the intent was to use a single query to check one or two things
(1. are we allowed to change the time at all? 2. are we allowed to
change it backwards?) but that's not what was actually done.

This was probably broken back in 2007:

https://mail-index.netbsd.org/source-changes/2007/11/25/msg193466.html

Module Name:    src
Committed By:   elad
Date:           Sun Nov 25 00:35:28 UTC 2007

Modified Files:
        src/share/man/man9: kauth.9
        src/sys/compat/hpux: hpux_compat.c
        src/sys/compat/linux/common: linux_misc_notalpha.c linux_time.c
        src/sys/compat/linux32/common: linux32_time.c
        src/sys/compat/netbsd32: netbsd32_time.c
        src/sys/dev: clockctl.c
        src/sys/kern: kern_time.c
        src/sys/secmodel/bsd44: secmodel_bsd44_suser.c
        src/sys/secmodel/securelevel: secmodel_securelevel.c
        src/sys/sys: timevar.h

Log Message:
Refactor time modification checks and place them in the secmodel code.

okay christos@


To generate a diff of this commit:
cvs rdiff -r1.55 -r1.56 src/share/man/man9/kauth.9
cvs rdiff -r1.97 -r1.98 src/sys/compat/hpux/hpux_compat.c
cvs rdiff -r1.96 -r1.97 src/sys/compat/linux/common/linux_misc_notalpha.c
cvs rdiff -r1.19 -r1.20 src/sys/compat/linux/common/linux_time.c
cvs rdiff -r1.13 -r1.14 src/sys/compat/linux32/common/linux32_time.c
cvs rdiff -r1.27 -r1.28 src/sys/compat/netbsd32/netbsd32_time.c
cvs rdiff -r1.22 -r1.23 src/sys/dev/clockctl.c
cvs rdiff -r1.131 -r1.132 src/sys/kern/kern_time.c
cvs rdiff -r1.39 -r1.40 src/sys/secmodel/bsd44/secmodel_bsd44_suser.c
cvs rdiff -r1.2 -r1.3 src/sys/secmodel/securelevel/secmodel_securelevel.c
cvs rdiff -r1.17 -r1.18 src/sys/sys/timevar.h


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.