2 * Copyright (c) 2006 nCircle Network Security, Inc.
5 * This software was developed by Robert N. M. Watson for the TrustedBSD
6 * Project under contract to nCircle Network Security, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
33 * Confirm that privilege is required in the cases using chown():
35 * - If the process euid does not match the file uid.
37 * - If the target uid is different than the current uid.
39 * - If the target gid changes and we the process is not a member of the new
43 #include <sys/types.h>
53 const gid_t gidset[] = {GID_WHEEL, GID_OWNER};
64 * Before beginning, set up group set for process. Place in wheel
65 * and owner groups; don't put in other group so that when we chown
66 * to the other group, it's as a non-member.
68 if (setgroups(2, gidset) < 0)
69 err(-1, "setgroups(2, {%d, %d})", GID_WHEEL, GID_OWNER);
72 * In the first pass, confirm that all works as desired with
75 * Check that chown when non-owner works fine. Do a no-op change to
76 * avoid other permission checks. Note that we can't request
77 * (-1, -1) and get an access control check, we have to request
78 * specific uid/gid that are not the same.
80 setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
81 if (chown(fpath, -1, GID_OWNER) < 0) {
82 warn("chown(%s, -1, %d) as root", fpath, GID_OWNER);
88 * Check that chown changing uid works with privilege.
90 setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
91 if (chown(fpath, UID_OTHER, -1) < 0) {
92 warn("chown(%s, %d, -1) as root", fpath, UID_OTHER);
98 * Check that can change the file group to one we are not a member of
99 * when running with privilege.
101 setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
102 if (chown(fpath, -1, GID_OTHER) < 0) {
103 warn("chown(%s, -1, %d) as root", fpath, GID_OTHER);
109 * Now, the same again, but without privilege.
111 * Confirm that we can't chown a file we don't own, even as a no-op.
113 setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
115 error = chown(fpath, -1, GID_OWNER);
117 warnx("chown(%s, -1, %d) succeeded as !root, non-owner",
121 if (errno != EPERM) {
122 warn("chown(%s, -1, %d) wrong errno %d as !root, non-owner",
123 fpath, GID_OWNER, errno);
130 * Check that we can't change the uid of the file without privilege,
131 * even though we own the file.
133 setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
135 error = chown(fpath, UID_OTHER, -1);
137 warnx("chown(%s, %d, -1) succeeded as !root", fpath,
141 if (errno != EPERM) {
142 warn("chown(%s, %d, -1) wrong errno %d as !root", fpath,
150 * Check that can't change the file group to one we are not a member
151 * of when running without privilege.
153 setup_file(fpath, UID_OWNER, GID_OWNER, 0600);
155 error = chown(fpath, -1, GID_OTHER);
157 warn("chown(%s, -1, %d) succeeded as !root", fpath, GID_OTHER);
160 if (errno != EPERM) {
161 warn("chown(%s, -1, %d) wrong errno %d as !root", fpath,
168 (void)seteuid(UID_ROOT);