kern/52454: [PATCH] let init change securelevel to -1 for single-user mode

Joshua Oreman oremanj at adsl-64-161-78-226.dsl.lsan03.pacbell.net
Mon May 19 19:20:11 PDT 2003


>Number:         52454
>Category:       kern
>Synopsis:       [PATCH] let init change securelevel to -1 for single-user mode
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon May 19 19:20:09 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Joshua Oreman
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
home 
>Environment:
System: FreeBSD webserver.get-linux.org 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Wed May 7 17:32:53 PDT 2003 root at webserver.get-linux.org:/usr/obj/usr/src/sys/GENERIC i386


	
>Description:
	Under OpenBSD, when `init' goes to single-user mode, it, and it alone,
	can change the securelevel back down to -1. To see why this would be
	useful, consider a firewall. It might normally run at securelevel 3
	to prevent tampering with firewall rules. However, suppose a rule
	change was needed. Without this functionality, the firewall would
	have to restart, disrupting service. With it, the firewall could
	simply drop to single-user, keeping connections, and change
	the rule. The patch adds that functionality to FreeBSD.

	
>How-To-Repeat:
	[not applicable]

	
>Fix:
Apply this patch to src/sys/kern/kern_mib.c:
--[snip]--
--- kern_mib.c.orig	Mon May 19 18:47:47 2003
+++ kern_mib.c	Mon May 19 18:54:36 2003
@@ -273,7 +273,8 @@
 	} else {
 		mtx_lock(&securelevel_mtx);
 		if (!regression_securelevel_nonmonotonic &&
-		    (level < securelevel)) {
+		    (level < securelevel) &&
+		    (req->td->td_proc->p_pid != 1)) {
 			mtx_unlock(&securelevel_mtx);
 			return (EPERM);
 		}
--[snip]--
and apply this patch to src/sbin/init/init.c:
--[snip]--
--- init.c.orig	Mon May 19 18:54:56 2003
+++ init.c	Mon May 19 19:09:38 2003
@@ -619,6 +619,25 @@
 		endpwent();
 #endif /* SECURE */
 
+		if (getsecuritylevel() > 0) {
+		    /*
+		     * It's safe to set newsecuritylevel to -1 here because,
+		     * even if securelevel was not originally -1, it will
+		     * be reset on return to multi-user.
+		     */
+		    int mib[2], newsecuritylevel = -1;
+		    syslog (LOG_INFO, "changing security level from %i to %i " 
+			    "for single-user mode", getsecuritylevel(), -1);
+		    
+		    mib[0] = CTL_KERN;
+		    mib[1] = KERN_SECURELVL;
+		    if (sysctl (mib, 2, NULL, NULL, &newsecuritylevel,
+				sizeof newsecuritylevel) == -1) {
+			warning ("unable to set securelevel; operations "
+				 "will continue at level %i", getsecuritylevel());
+		    }
+		}
+
 #ifdef DEBUGSHELL
 		{
 			char *cp = altshell;
--[snip]--

Recompile init and the kernel, reboot, and the securelevel
will go down for single-user mode. This is not a security
hole because only `init' (pid 1) has the authority to do
this.

	


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list