1/*-
2 * Copyright (c) 2007 Robert M. M. Watson
3 * All rights reserved.
4 *
5 * This software was developed by Robert N. M. Watson for the TrustedBSD
6 * Project.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR, NCIRCLE NETWORK SECURITY,
21 * INC., OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
23 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD$
30 */
31
32/*
33 * Confirm that when security.bsd.unprivileged_read_msgbuf is set to 0,
34 * privilege is required to read the kernel message buffer.
35 */
36
37#include <sys/types.h>
38#include <sys/sysctl.h>
39
40#include <err.h>
41#include <errno.h>
42#include <stdio.h>
43
44#include "main.h"
45
46#define	MSGBUF_CONTROL_NAME	"security.bsd.unprivileged_read_msgbuf"
47#define	MSGBUF_NAME		"kern.msgbuf"
48
49/*
50 * We must query and save the original value, then restore it when done.
51 */
52static int unprivileged_read_msgbuf;
53static int unprivileged_read_msgbuf_initialized;
54
55int
56priv_msgbuf_privonly_setup(int asroot, int injail, struct test *test)
57{
58	size_t len;
59	int newval;
60
61	/*
62	 * Separately query and set to make debugging easier.
63	 */
64	len = sizeof(unprivileged_read_msgbuf);
65	if (sysctlbyname(MSGBUF_CONTROL_NAME, &unprivileged_read_msgbuf,
66	    &len, NULL, 0) < 0) {
67		warn("priv_msgbuf_privonly_setup: sysctlbyname query");
68		return (-1);
69	}
70	newval = 0;
71	if (sysctlbyname(MSGBUF_CONTROL_NAME, NULL, NULL, &newval,
72	    sizeof(newval)) < 0) {
73		warn("priv_msgbuf_privonly_setup: sysctlbyname set");
74		return (-1);
75	}
76	unprivileged_read_msgbuf_initialized = 1;
77	return (0);
78}
79
80void
81priv_msgbuf_privonly(int asroot, int injail, struct test *test)
82{
83	size_t len;
84	int error;
85
86	error = sysctlbyname(MSGBUF_NAME, NULL, &len, NULL, 0);
87	if (asroot && injail)
88		expect("priv_msgbuf_privonly(asroot, injail)", error, -1,
89		    EPERM);
90	if (asroot && !injail)
91		expect("priv_msgbuf_privonly(asroot, !injail)", error, 0, 0);
92	if (!asroot && injail)
93		expect("priv_msgbuf_privonly(!asroot, injail)", error, -1,
94		    EPERM);
95	if (!asroot && !injail)
96		expect("priv_msgbuf_privonly(!asroot, !injail)", error, -1,
97		    EPERM);
98}
99
100int
101priv_msgbuf_unprivok_setup(int asroot, int injail, struct test *test)
102{
103	size_t len;
104	int newval;
105
106	/*
107	 * Separately query and set to make debugging easier.
108	 */
109	len = sizeof(unprivileged_read_msgbuf);
110	if (sysctlbyname(MSGBUF_CONTROL_NAME, &unprivileged_read_msgbuf, &len,
111	    NULL, 0) < 0) {
112		warn("priv_msgbuf_unprivok_setup: sysctlbyname query");
113		return (-1);
114	}
115	newval = 1;
116	if (sysctlbyname(MSGBUF_CONTROL_NAME, NULL, NULL, &newval,
117	    sizeof(newval)) < 0) {
118		warn("priv_msgbuf_unprivok_setup: sysctlbyname set");
119		return (-1);
120	}
121	unprivileged_read_msgbuf_initialized = 1;
122	return (0);
123}
124
125void
126priv_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