From lefevre@d074.paris-222.cybercable.fr Wed Nov 17 05:02:14 1999
Return-Path: <lefevre@d074.paris-222.cybercable.fr>
Received: from camus.cybercable.fr (camus.cybercable.fr [212.198.0.200])
	by hub.freebsd.org (Postfix) with SMTP id 270B314BC2
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 17 Nov 1999 05:02:13 -0800 (PST)
	(envelope-from lefevre@d074.paris-222.cybercable.fr)
Received: (qmail 821369 invoked from network); 17 Nov 1999 13:02:11 -0000
Received: from d074.paris-222.cybercable.fr ([212.198.222.74]) (envelope-sender <lefevre@d074.paris-222.cybercable.fr>)
          by camus.cybercable.fr (qmail-ldap-1.03) with SMTP
          for <FreeBSD-gnats-submit@freebsd.org>; 17 Nov 1999 13:02:11 -0000
Received: (from root@localhost)
	by d074.paris-222.cybercable.fr (8.9.3/8.9.3) id OAA00956;
	Wed, 17 Nov 1999 14:02:11 +0100 (CET)
	(envelope-from lefevre)
Message-Id: <199911171302.OAA00956@d074.paris-222.cybercable.fr>
Date: Wed, 17 Nov 1999 14:02:11 +0100 (CET)
From: root@d074.paris-222.cybercable.fr
Sender: lefevre@d074.paris-222.cybercable.fr
Reply-To: clefevre@citeweb.net
To: FreeBSD-gnats-submit@freebsd.org
Subject: /etc/init vs kern.securelevel incoherence
X-Send-Pr-Version: 3.2

>Number:         14941
>Category:       kern
>Synopsis:       /etc/init vs kern.securelevel incoherence
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kato
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 17 05:10:00 PST 1999
>Closed-Date:    Sat Dec 4 06:21:10 PST 1999
>Last-Modified:  Sat Dec  4 06:28:02 PST 1999
>Originator:     Cyrille Lefevre
>Release:        FreeBSD 3.3-STABLE i386
>Organization:
ACME
>Environment:

FreeBSD gits 3.3-STABLE FreeBSD 3.3-STABLE #5: Sun Nov 14 04:01:58 CET 1999	root@gits:/disk3/3.3-STABLE/src/sys/compile/CUSTOM  i386

>Description:

	the init(8) manual says :

	Any super-user process can raise the security level, but only
	init can lower it.
	...
	If the security level is initially -1, then init leaves it
	unchanged.  Otherwise, init arranges to run the system in
	level 0 mode while single-user and in level 1 mode while
	multi-user. 

	but in the kernel says :

	in function sysctl_kern_securelvl in /sys/kern/kern_mib.c :

		if (securelevel > 1 && level < securelevel)
			return (EPERM);

	as well as the sysctl(3) manual and some other docs :

	KERN_SECURELVL
		The system security level.  This level may be raised
		by processes with appropriate privilege.  It may not
		be lowered.

	so, if you have a security level greater or equal to 1,
	even when going to single-user mode, you cannot lower
	the security level to 0 to install a new kernel and you
	have reboot into single-user or to set the
	kern_securelevel_enable to NO in the /etc/rc.conf file,
	then reboot.

>How-To-Repeat:

	in /etc/rc.conf :

	kern_securelevel_enable="YES"
	kern_securelevel="0"

	boot to multi-user mode then switch to single user mode using :

	init 1

	you got a syslog message saying :

	cannot change kernel security level from 1 to 0: Permission denied.

>Fix:

# diff -rcb kern_mib.c.orig kern_mib.c
*** kern_mib.c.orig	Wed Nov 17 03:16:52 1999
--- kern_mib.c	Wed Nov 17 03:22:46 1999
***************
*** 138,144 ****
		error = sysctl_handle_int(oidp, &level, 0, req);
		if (error || !req->newptr)
			return (error);
!		if (level < securelevel)
			return (EPERM);
		securelevel = level;
		return (error);
--- 138,148 ----
		error = sysctl_handle_int(oidp, &level, 0, req);
		if (error || !req->newptr)
			return (error);
! #ifdef notdef
!		printf ("pid=%d curproc=%p initproc=%p\n",
!			curproc->p_pid, curproc, initproc);
! #endif
!		if (curproc != initproc && level < securelevel)
			return (EPERM);
		securelevel = level;
		return (error);

a much portable solution would be :

# diff -rcb kern_mib.c.orig kern_mib.c
*** kern_mib.c.orig	Wed Nov 17 03:16:52 1999
--- kern_mib.c	Wed Nov 17 03:22:46 1999
***************
*** 138,144 ****
		error = sysctl_handle_int(oidp, &level, 0, req);
		if (error || !req->newptr)
			return (error);
!		if (level < securelevel)
			return (EPERM);
		securelevel = level;
		return (error);
--- 138,148 ----
		error = sysctl_handle_int(oidp, &level, 0, req);
		if (error || !req->newptr)
			return (error);
! #ifdef notdef
!		printf ("pid=%d curproc=%p initproc=%p\n",
!			curproc->p_pid, curproc, initproc);
! #endif
!		if (curproc->p_pid != 1 && level < securelevel)
			return (EPERM);
		securelevel = level;
		return (error);

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->suspended 
State-Changed-By: sheldonh 
State-Changed-When: Wed Nov 17 05:19:41 PST 1999 
State-Changed-Why:  
This situation was dealt with in rev 1.19 of init.8 and rev 1.36 of 
init.c, although these changes have not yet been merged back to the  
stable branch.  I'm leaving this PR in the suspended state as an 
kato has other such 
PR's lying around, he can close this as a duplicate. 


Responsible-Changed-From-To: freebsd-bugs->kato 
Responsible-Changed-By: sheldonh 
Responsible-Changed-When: Wed Nov 17 05:19:41 PST 1999 
Responsible-Changed-Why:  
kato's commit to CURRENT. 
State-Changed-From-To: suspended->closed 
State-Changed-By: kato 
State-Changed-When: Sat Dec 4 06:21:10 PST 1999 
State-Changed-Why:  
The inconsistency between the manual page and init.c was solved in both  
current and RELENG_3.  FreeBSD's init cannot downgrade securelevel. 
>Unformatted:
