1224133Sdim/*-
2224133Sdim * Copyright (c) 2007 Robert M. M. Watson
3224133Sdim * All rights reserved.
4224133Sdim *
5224133Sdim * This software was developed by Robert N. M. Watson for the TrustedBSD
6224133Sdim * Project.
7224133Sdim *
8224133Sdim * Redistribution and use in source and binary forms, with or without
9224133Sdim * modification, are permitted provided that the following conditions
10224133Sdim * are met:
11224133Sdim * 1. Redistributions of source code must retain the above copyright
12224133Sdim *    notice, this list of conditions and the following disclaimer.
13224133Sdim * 2. Redistributions in binary form must reproduce the above copyright
14224133Sdim *    notice, this list of conditions and the following disclaimer in the
15224133Sdim *    documentation and/or other materials provided with the distribution.
16249423Sdim *
17224133Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18224133Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19224133Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20224133Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
21224133Sdim * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22224133Sdim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23224133Sdim * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24224133Sdim * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25224133Sdim * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26224133Sdim * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27224133Sdim * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28224133Sdim *
29234353Sdim * $FreeBSD$
30234353Sdim */
31224133Sdim
32234353Sdim/*
33234353Sdim * Confirm that when security.bsd.unprivileged_read_msgbuf is set to 0,
34234353Sdim * privilege is required to read the kernel message buffer.
35234353Sdim */
36234353Sdim
37234353Sdim#include <sys/types.h>
38234353Sdim#include <sys/sysctl.h>
39224133Sdim
40224133Sdim#include <err.h>
41243830Sdim#include <errno.h>
42224133Sdim#include <stdio.h>
43224133Sdim
44224133Sdim#include "main.h"
45234353Sdim
46234353Sdim#define	MSGBUF_CONTROL_NAME	"security.bsd.unprivileged_read_msgbuf"
47234353Sdim#define	MSGBUF_NAME		"kern.msgbuf"
48234353Sdim
49234353Sdim/*
50234353Sdim * We must query and save the original value, then restore it when done.
51234353Sdim */
52234353Sdimstatic int unprivileged_read_msgbuf;
53234353Sdimstatic int unprivileged_read_msgbuf_initialized;
54234353Sdim
55234353Sdimint
56243830Sdimpriv_msgbuf_privonly_setup(int asroot, int injail, struct test *test)
57234353Sdim{
58234353Sdim	size_t len;
59234353Sdim	int newval;
60224133Sdim
61224133Sdim	/*
62224133Sdim	 * Separately query and set to make debugging easier.
63243830Sdim	 */
64243830Sdim	len = sizeof(unprivileged_read_msgbuf);
65243830Sdim	if (sysctlbyname(MSGBUF_CONTROL_NAME, &unprivileged_read_msgbuf,
66224133Sdim	    &len, NULL, 0) < 0) {
67224133Sdim		warn("priv_msgbuf_privonly_setup: sysctlbyname query");
68224133Sdim		return (-1);
69224133Sdim	}
70224133Sdim	newval = 0;
71224133Sdim	if (sysctlbyname(MSGBUF_CONTROL_NAME, NULL, NULL, &newval,
72243830Sdim	    sizeof(newval)) < 0) {
73243830Sdim		warn("priv_msgbuf_privonly_setup: sysctlbyname set");
74243830Sdim		return (-1);
75243830Sdim	}
76243830Sdim	unprivileged_read_msgbuf_initialized = 1;
77243830Sdim	return (0);
78243830Sdim}
79243830Sdim
80224133Sdimvoid
81224133Sdimpriv_msgbuf_privonly(int asroot, int injail, struct test *test)
82224133Sdim{
83234353Sdim	size_t len;
84234353Sdim	int error;
85224133Sdim
86224133Sdim	error = sysctlbyname(MSGBUF_NAME, NULL, &len, NULL, 0);
87224133Sdim	if (asroot && injail)
88224133Sdim		expect("priv_msgbuf_privonly(asroot, injail)", error, -1,
89224133Sdim		    EPERM);
90224133Sdim	if (asroot && !injail)
91224133Sdim		expect("priv_msgbuf_privonly(asroot, !injail)", error, 0, 0);
92224133Sdim	if (!asroot && injail)
93243830Sdim		expect("priv_msgbuf_privonly(!asroot, injail)", error, -1,
94224133Sdim		    EPERM);
95224133Sdim	if (!asroot && !injail)
96234353Sdim		expect("priv_msgbuf_privonly(!asroot, !injail)", error, -1,
97224133Sdim		    EPERM);
98224133Sdim}
99224133Sdim
100234353Sdimint
101224133Sdimpriv_msgbuf_unprivok_setup(int asroot, int injail, struct test *test)
102224133Sdim{
103224133Sdim	size_t len;
104224133Sdim	int newval;
105224133Sdim
106224133Sdim	/*
107224133Sdim	 * Separately query and set to make debugging easier.
108224133Sdim	 */
109234353Sdim	len = sizeof(unprivileged_read_msgbuf);
110234353Sdim	if (sysctlbyname(MSGBUF_CONTROL_NAME, &unprivileged_read_msgbuf, &len,
111234353Sdim	    NULL, 0) < 0) {
112224133Sdim		warn("priv_msgbuf_unprivok_setup: sysctlbyname query");
113224133Sdim		return (-1);
114224133Sdim	}
115224133Sdim	newval = 1;
116224133Sdim	if (sysctlbyname(MSGBUF_CONTROL_NAME, NULL, NULL, &newval,
117224133Sdim	    sizeof(newval)) < 0) {
118224133Sdim		warn("priv_msgbuf_unprivok_setup: sysctlbyname set");
119224133Sdim		return (-1);
120224133Sdim	}
121224133Sdim	unprivileged_read_msgbuf_initialized = 1;
122224133Sdim	return (0);
123224133Sdim}
124224133Sdim
125224133Sdimvoid
126224133Sdimpriv_msgbuf_unprivok(int asroot, int injail, struct test *test)
127{
128	size_t len;
129	int error;
130
131	error = sysctlbyname(MSGBUF_NAME, NULL, &len, NULL, 0);
132	if (asroot && injail)
133		expect("priv_msgbuf_unprivok(asroot, injail)", error, 0, 0);
134	if (asroot && !injail)
135		expect("priv_msgbuf_unprivok(asroot, !injail)", error, 0, 0);
136	if (!asroot && injail)
137		expect("priv_msgbuf_unprivok(!asroot, injail)", error, 0, 0);
138	if (!asroot && !injail)
139		expect("priv_msgbuf_unprivok(!asroot, !injail)", error, 0, 0);
140}
141
142void
143priv_msgbuf_cleanup(int asroot, int injail, struct test *test)
144{
145
146	if (unprivileged_read_msgbuf_initialized) {
147		(void)sysctlbyname(MSGBUF_NAME, NULL, NULL,
148		    &unprivileged_read_msgbuf,
149		    sizeof(unprivileged_read_msgbuf));
150		unprivileged_read_msgbuf_initialized = 0;
151	}
152}
153