1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 Tim Kientzle
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24228753Smm */
25228753Smm#include "test.h"
26228763Smm__FBSDID("$FreeBSD$");
27228753Smm
28232153Smm#if !defined(_WIN32) || defined(__CYGWIN__)
29228753Smm
30228753Smm#define UMASK 022
31228753Smm
32228753Smmstatic long _default_gid = -1;
33228753Smmstatic long _invalid_gid = -1;
34228753Smmstatic long _alt_gid = -1;
35228753Smm
36228753Smm/*
37228753Smm * To fully test SGID restores, we need three distinct GIDs to work
38228753Smm * with:
39228753Smm *    * the GID that files are created with by default (for the
40228753Smm *      current user in the current directory)
41228753Smm *    * An "alt gid" that this user can create files with
42228753Smm *    * An "invalid gid" that this user is not permitted to create
43228753Smm *      files with.
44228753Smm * The second fails if this user doesn't belong to at least two groups;
45228753Smm * the third fails if the current user is root.
46228753Smm */
47228753Smmstatic void
48228753Smmsearchgid(void)
49228753Smm{
50228753Smm	static int   _searched = 0;
51228753Smm	uid_t uid = getuid();
52228753Smm	gid_t gid = 0;
53228753Smm	unsigned int n;
54228753Smm	struct stat st;
55228753Smm	int fd;
56228753Smm
57228753Smm	/* If we've already looked this up, we're done. */
58228753Smm	if (_searched)
59228753Smm		return;
60228753Smm	_searched = 1;
61228753Smm
62228753Smm	/* Create a file on disk in the current default dir. */
63228753Smm	fd = open("test_gid", O_CREAT | O_BINARY, 0664);
64228753Smm	failure("Couldn't create a file for gid testing.");
65228753Smm	assert(fd > 0);
66228753Smm
67228753Smm	/* See what GID it ended up with.  This is our "valid" GID. */
68228753Smm	assert(fstat(fd, &st) == 0);
69228753Smm	_default_gid = st.st_gid;
70228753Smm
71228753Smm	/* Find a GID for which fchown() fails.  This is our "invalid" GID. */
72228753Smm	_invalid_gid = -1;
73228753Smm	/* This loop stops when we wrap the gid or examine 10,000 gids. */
74228753Smm	for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
75228753Smm		if (fchown(fd, uid, gid) != 0) {
76228753Smm			_invalid_gid = gid;
77228753Smm			break;
78228753Smm		}
79228753Smm	}
80228753Smm
81228753Smm	/*
82228753Smm	 * Find a GID for which fchown() succeeds, but which isn't the
83228753Smm	 * default.  This is the "alternate" gid.
84228753Smm	 */
85228753Smm	_alt_gid = -1;
86228753Smm	for (gid = 0, n = 0; gid == n && n < 10000 ; n++, gid++) {
87228753Smm		/* _alt_gid must be different than _default_gid */
88228753Smm		if (gid == (gid_t)_default_gid)
89228753Smm			continue;
90228753Smm		if (fchown(fd, uid, gid) == 0) {
91228753Smm			_alt_gid = gid;
92228753Smm			break;
93228753Smm		}
94228753Smm	}
95228753Smm	close(fd);
96228753Smm}
97228753Smm
98228753Smmstatic int
99228753Smmaltgid(void)
100228753Smm{
101228753Smm	searchgid();
102228753Smm	return (_alt_gid);
103228753Smm}
104228753Smm
105228753Smmstatic int
106228753Smminvalidgid(void)
107228753Smm{
108228753Smm	searchgid();
109228753Smm	return (_invalid_gid);
110228753Smm}
111228753Smm
112228753Smmstatic int
113228753Smmdefaultgid(void)
114228753Smm{
115228753Smm	searchgid();
116228753Smm	return (_default_gid);
117228753Smm}
118228753Smm#endif
119228753Smm
120228753Smm/*
121228753Smm * Exercise permission and ownership restores.
122228753Smm * In particular, try to exercise a bunch of border cases related
123228753Smm * to files/dirs that already exist, SUID/SGID bits, etc.
124228753Smm */
125228753Smm
126228753SmmDEFINE_TEST(test_write_disk_perms)
127228753Smm{
128232153Smm#if defined(_WIN32) && !defined(__CYGWIN__)
129228753Smm	skipping("archive_write_disk interface");
130228753Smm#else
131228753Smm	struct archive *a;
132228753Smm	struct archive_entry *ae;
133228753Smm	struct stat st;
134228753Smm
135228753Smm	assertUmask(UMASK);
136228753Smm
137228753Smm	/*
138228753Smm	 * Set ownership of the current directory to the group of this
139228753Smm	 * process.  Otherwise, the SGID tests below fail if the
140228753Smm	 * /tmp directory is owned by a group to which we don't belong
141228753Smm	 * and we're on a system where group ownership is inherited.
142228753Smm	 * (Because we're not allowed to SGID files with defaultgid().)
143228753Smm	 */
144228753Smm	assertEqualInt(0, chown(".", getuid(), getgid()));
145228753Smm
146228753Smm	/* Create an archive_write_disk object. */
147228753Smm	assert((a = archive_write_disk_new()) != NULL);
148228753Smm
149228753Smm	/* Write a regular file to it. */
150228753Smm	assert((ae = archive_entry_new()) != NULL);
151228753Smm	archive_entry_copy_pathname(ae, "file_0755");
152228753Smm	archive_entry_set_mode(ae, S_IFREG | 0777);
153228753Smm	assert(0 == archive_write_header(a, ae));
154228753Smm	assert(0 == archive_write_finish_entry(a));
155228753Smm	archive_entry_free(ae);
156228753Smm
157228753Smm	/* Write a regular file, then write over it. */
158228753Smm	/* For files, the perms should get updated. */
159228753Smm	assert((ae = archive_entry_new()) != NULL);
160228753Smm	archive_entry_copy_pathname(ae, "file_overwrite_0144");
161228753Smm	archive_entry_set_mode(ae, S_IFREG | 0777);
162228753Smm	assert(0 == archive_write_header(a, ae));
163228753Smm	archive_entry_free(ae);
164228753Smm	assert(0 == archive_write_finish_entry(a));
165228753Smm	/* Check that file was created with different perms. */
166228753Smm	assert(0 == stat("file_overwrite_0144", &st));
167228753Smm	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
168228753Smm	assert((st.st_mode & 07777) != 0144);
169228753Smm	/* Overwrite, this should change the perms. */
170228753Smm	assert((ae = archive_entry_new()) != NULL);
171228753Smm	archive_entry_copy_pathname(ae, "file_overwrite_0144");
172228753Smm	archive_entry_set_mode(ae, S_IFREG | 0144);
173228753Smm	assert(0 == archive_write_header(a, ae));
174228753Smm	archive_entry_free(ae);
175228753Smm	assert(0 == archive_write_finish_entry(a));
176228753Smm
177228753Smm	/* Write a regular dir. */
178228753Smm	assert((ae = archive_entry_new()) != NULL);
179228753Smm	archive_entry_copy_pathname(ae, "dir_0514");
180228753Smm	archive_entry_set_mode(ae, S_IFDIR | 0514);
181228753Smm	assert(0 == archive_write_header(a, ae));
182228753Smm	archive_entry_free(ae);
183228753Smm	assert(0 == archive_write_finish_entry(a));
184228753Smm
185228753Smm	/* Overwrite an existing dir. */
186228753Smm	/* For dir, the first perms should get left. */
187228753Smm	assertMakeDir("dir_overwrite_0744", 0744);
188228753Smm	/* Check original perms. */
189228753Smm	assert(0 == stat("dir_overwrite_0744", &st));
190228753Smm	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
191228753Smm	assert((st.st_mode & 0777) == 0744);
192228753Smm	/* Overwrite shouldn't edit perms. */
193228753Smm	assert((ae = archive_entry_new()) != NULL);
194228753Smm	archive_entry_copy_pathname(ae, "dir_overwrite_0744");
195228753Smm	archive_entry_set_mode(ae, S_IFDIR | 0777);
196228753Smm	assert(0 == archive_write_header(a, ae));
197228753Smm	archive_entry_free(ae);
198228753Smm	assert(0 == archive_write_finish_entry(a));
199228753Smm	/* Make sure they're unchanged. */
200228753Smm	assert(0 == stat("dir_overwrite_0744", &st));
201228753Smm	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
202228753Smm	assert((st.st_mode & 0777) == 0744);
203228753Smm
204228753Smm	/* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
205228753Smm	assert((ae = archive_entry_new()) != NULL);
206228753Smm	archive_entry_copy_pathname(ae, "file_no_suid");
207228753Smm	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777);
208228753Smm	archive_write_disk_set_options(a, 0);
209228753Smm	assert(0 == archive_write_header(a, ae));
210228753Smm	assert(0 == archive_write_finish_entry(a));
211228753Smm
212228753Smm	/* Write a regular file with ARCHIVE_EXTRACT_PERM. */
213228753Smm	assert(archive_entry_clear(ae) != NULL);
214228753Smm	archive_entry_copy_pathname(ae, "file_0777");
215228753Smm	archive_entry_set_mode(ae, S_IFREG | 0777);
216228753Smm	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
217228753Smm	assert(0 == archive_write_header(a, ae));
218228753Smm	assert(0 == archive_write_finish_entry(a));
219228753Smm
220228753Smm	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */
221228753Smm	assert(archive_entry_clear(ae) != NULL);
222228753Smm	archive_entry_copy_pathname(ae, "file_4742");
223228753Smm	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
224228753Smm	archive_entry_set_uid(ae, getuid());
225228753Smm	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
226228753Smm	assert(0 == archive_write_header(a, ae));
227228753Smm	assert(0 == archive_write_finish_entry(a));
228228753Smm
229228753Smm	/*
230228753Smm	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit,
231228753Smm	 * but wrong uid.  POSIX says you shouldn't restore SUID bit
232228753Smm	 * unless the UID could be restored.
233228753Smm	 */
234228753Smm	assert(archive_entry_clear(ae) != NULL);
235228753Smm	archive_entry_copy_pathname(ae, "file_bad_suid");
236228753Smm	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
237228753Smm	archive_entry_set_uid(ae, getuid() + 1);
238228753Smm	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
239228753Smm	assertA(0 == archive_write_header(a, ae));
240228753Smm	/*
241228753Smm	 * Because we didn't ask for owner, the failure to
242228753Smm	 * restore SUID shouldn't return a failure.
243228753Smm	 * We check below to make sure SUID really wasn't set.
244228753Smm	 * See more detailed comments below.
245228753Smm	 */
246228753Smm	failure("Opportunistic SUID failure shouldn't return error.");
247228753Smm	assertEqualInt(0, archive_write_finish_entry(a));
248228753Smm
249228753Smm        if (getuid() != 0) {
250228753Smm		assert(archive_entry_clear(ae) != NULL);
251228753Smm		archive_entry_copy_pathname(ae, "file_bad_suid2");
252228753Smm		archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
253228753Smm		archive_entry_set_uid(ae, getuid() + 1);
254228753Smm		archive_write_disk_set_options(a,
255228753Smm		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
256228753Smm		assertA(0 == archive_write_header(a, ae));
257228753Smm		/* Owner change should fail here. */
258228753Smm		failure("Non-opportunistic SUID failure should return error.");
259228753Smm		assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
260228753Smm	}
261228753Smm
262228753Smm	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
263228753Smm	assert(archive_entry_clear(ae) != NULL);
264228753Smm	archive_entry_copy_pathname(ae, "file_perm_sgid");
265228753Smm	archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
266228753Smm	archive_entry_set_gid(ae, defaultgid());
267228753Smm	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
268228753Smm	assert(0 == archive_write_header(a, ae));
269228753Smm	failure("Setting SGID bit should succeed here.");
270228753Smm	assertEqualIntA(a, 0, archive_write_finish_entry(a));
271228753Smm
272228753Smm	if (altgid() == -1) {
273228753Smm		/*
274228753Smm		 * Current user must belong to at least two groups or
275228753Smm		 * else we can't test setting the GID to another group.
276228753Smm		 */
277228753Smm		skipping("Current user can't test gid restore: must belong to more than one group.");
278228753Smm	} else {
279228753Smm		/*
280228753Smm		 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit
281228753Smm		 * but without ARCHIVE_EXTRACT_OWNER.
282228753Smm		 */
283228753Smm		/*
284228753Smm		 * This is a weird case: The user has asked for permissions to
285228753Smm		 * be restored but not asked for ownership to be restored.  As
286228753Smm		 * a result, the default file creation will create a file with
287228753Smm		 * the wrong group.  There are several possible behaviors for
288228753Smm		 * libarchive in this scenario:
289228753Smm		 *  = Set the SGID bit.  It is wrong and a security hole to
290228753Smm		 *    set SGID with the wrong group.  Even POSIX thinks so.
291228753Smm		 *  = Implicitly set the group.  I don't like this.
292228753Smm		 *  = drop the SGID bit and warn (the old libarchive behavior)
293228753Smm		 *  = drop the SGID bit and don't warn (the current libarchive
294228753Smm		 *    behavior).
295228753Smm		 * The current behavior sees SGID/SUID restore when you
296228753Smm		 * don't ask for owner restore as an "opportunistic"
297228753Smm		 * action.  That is, libarchive should do it if it can,
298228753Smm		 * but if it can't, it's not an error.
299228753Smm		 */
300228753Smm		assert(archive_entry_clear(ae) != NULL);
301228753Smm		archive_entry_copy_pathname(ae, "file_alt_sgid");
302228753Smm		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
303228753Smm		archive_entry_set_uid(ae, getuid());
304228753Smm		archive_entry_set_gid(ae, altgid());
305228753Smm		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
306228753Smm		assert(0 == archive_write_header(a, ae));
307228753Smm		failure("Setting SGID bit should fail because of group mismatch but the failure should be silent because we didn't ask for the group to be set.");
308228753Smm		assertEqualIntA(a, 0, archive_write_finish_entry(a));
309228753Smm
310228753Smm		/*
311228753Smm		 * As above, but add _EXTRACT_OWNER to verify that it
312228753Smm		 * does succeed.
313228753Smm		 */
314228753Smm		assert(archive_entry_clear(ae) != NULL);
315228753Smm		archive_entry_copy_pathname(ae, "file_alt_sgid_owner");
316228753Smm		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
317228753Smm		archive_entry_set_uid(ae, getuid());
318228753Smm		archive_entry_set_gid(ae, altgid());
319228753Smm		archive_write_disk_set_options(a,
320228753Smm		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
321228753Smm		assert(0 == archive_write_header(a, ae));
322228753Smm		failure("Setting SGID bit should succeed here.");
323228753Smm		assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
324228753Smm	}
325228753Smm
326228753Smm	/*
327228753Smm	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit,
328228753Smm	 * but wrong GID.  POSIX says you shouldn't restore SGID bit
329228753Smm	 * unless the GID could be restored.
330228753Smm	 */
331228753Smm	if (invalidgid() == -1) {
332228753Smm		/* This test always fails for root. */
333228753Smm		printf("Running as root: Can't test SGID failures.\n");
334228753Smm	} else {
335228753Smm		assert(archive_entry_clear(ae) != NULL);
336228753Smm		archive_entry_copy_pathname(ae, "file_bad_sgid");
337228753Smm		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
338228753Smm		archive_entry_set_gid(ae, invalidgid());
339228753Smm		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
340228753Smm		assertA(0 == archive_write_header(a, ae));
341228753Smm		failure("This SGID restore should fail without an error.");
342228753Smm		assertEqualIntA(a, 0, archive_write_finish_entry(a));
343228753Smm
344228753Smm		assert(archive_entry_clear(ae) != NULL);
345228753Smm		archive_entry_copy_pathname(ae, "file_bad_sgid2");
346228753Smm		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
347228753Smm		archive_entry_set_gid(ae, invalidgid());
348228753Smm		archive_write_disk_set_options(a,
349228753Smm		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
350228753Smm		assertA(0 == archive_write_header(a, ae));
351228753Smm		failure("This SGID restore should fail with an error.");
352228753Smm		assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
353228753Smm	}
354228753Smm
355228753Smm	/* Set ownership should fail if we're not root. */
356228753Smm	if (getuid() == 0) {
357228753Smm		printf("Running as root: Can't test setuid failures.\n");
358228753Smm	} else {
359228753Smm		assert(archive_entry_clear(ae) != NULL);
360228753Smm		archive_entry_copy_pathname(ae, "file_bad_owner");
361228753Smm		archive_entry_set_mode(ae, S_IFREG | 0744);
362228753Smm		archive_entry_set_uid(ae, getuid() + 1);
363228753Smm		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER);
364228753Smm		assertA(0 == archive_write_header(a, ae));
365228753Smm		assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a));
366228753Smm	}
367228753Smm
368232153Smm	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
369228753Smm	archive_entry_free(ae);
370228753Smm
371228753Smm	/* Test the entries on disk. */
372228753Smm	assert(0 == stat("file_0755", &st));
373228753Smm	failure("file_0755: st.st_mode=%o", st.st_mode);
374228753Smm	assert((st.st_mode & 07777) == 0755);
375228753Smm
376228753Smm	assert(0 == stat("file_overwrite_0144", &st));
377228753Smm	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
378228753Smm	assert((st.st_mode & 07777) == 0144);
379228753Smm
380228753Smm	assert(0 == stat("dir_0514", &st));
381228753Smm	failure("dir_0514: st.st_mode=%o", st.st_mode);
382228753Smm	assert((st.st_mode & 07777) == 0514);
383228753Smm
384228753Smm	assert(0 == stat("dir_overwrite_0744", &st));
385228753Smm	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
386228753Smm	assert((st.st_mode & 0777) == 0744);
387228753Smm
388228753Smm	assert(0 == stat("file_no_suid", &st));
389228753Smm	failure("file_0755: st.st_mode=%o", st.st_mode);
390228753Smm	assert((st.st_mode & 07777) == 0755);
391228753Smm
392228753Smm	assert(0 == stat("file_0777", &st));
393228753Smm	failure("file_0777: st.st_mode=%o", st.st_mode);
394228753Smm	assert((st.st_mode & 07777) == 0777);
395228753Smm
396228753Smm	/* SUID bit should get set here. */
397228753Smm	assert(0 == stat("file_4742", &st));
398228753Smm	failure("file_4742: st.st_mode=%o", st.st_mode);
399228753Smm	assert((st.st_mode & 07777) == (S_ISUID | 0742));
400228753Smm
401228753Smm	/* SUID bit should NOT have been set here. */
402228753Smm	assert(0 == stat("file_bad_suid", &st));
403228753Smm	failure("file_bad_suid: st.st_mode=%o", st.st_mode);
404228753Smm	assert((st.st_mode & 07777) == (0742));
405228753Smm
406228753Smm	/* Some things don't fail if you're root, so suppress this. */
407228753Smm	if (getuid() != 0) {
408228753Smm		/* SUID bit should NOT have been set here. */
409228753Smm		assert(0 == stat("file_bad_suid2", &st));
410228753Smm		failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
411228753Smm		assert((st.st_mode & 07777) == (0742));
412228753Smm	}
413228753Smm
414228753Smm	/* SGID should be set here. */
415228753Smm	assert(0 == stat("file_perm_sgid", &st));
416228753Smm	failure("file_perm_sgid: st.st_mode=%o", st.st_mode);
417228753Smm	assert((st.st_mode & 07777) == (S_ISGID | 0742));
418228753Smm
419228753Smm	if (altgid() != -1) {
420228753Smm		/* SGID should not be set here. */
421228753Smm		assert(0 == stat("file_alt_sgid", &st));
422228753Smm		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
423228753Smm		assert((st.st_mode & 07777) == (0742));
424228753Smm
425228753Smm		/* SGID should be set here. */
426228753Smm		assert(0 == stat("file_alt_sgid_owner", &st));
427228753Smm		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
428228753Smm		assert((st.st_mode & 07777) == (S_ISGID | 0742));
429228753Smm	}
430228753Smm
431228753Smm	if (invalidgid() != -1) {
432228753Smm		/* SGID should NOT be set here. */
433228753Smm		assert(0 == stat("file_bad_sgid", &st));
434228753Smm		failure("file_bad_sgid: st.st_mode=%o", st.st_mode);
435228753Smm		assert((st.st_mode & 07777) == (0742));
436228753Smm		/* SGID should NOT be set here. */
437228753Smm		assert(0 == stat("file_bad_sgid2", &st));
438228753Smm		failure("file_bad_sgid2: st.st_mode=%o", st.st_mode);
439228753Smm		assert((st.st_mode & 07777) == (0742));
440228753Smm	}
441228753Smm
442228753Smm	if (getuid() != 0) {
443228753Smm		assert(0 == stat("file_bad_owner", &st));
444228753Smm		failure("file_bad_owner: st.st_mode=%o", st.st_mode);
445228753Smm		assert((st.st_mode & 07777) == (0744));
446228753Smm		failure("file_bad_owner: st.st_uid=%d getuid()=%d",
447228753Smm		    st.st_uid, getuid());
448228753Smm		/* The entry had getuid()+1, but because we're
449228753Smm		 * not root, we should not have been able to set that. */
450228753Smm		assert(st.st_uid == getuid());
451228753Smm	}
452228753Smm#endif
453228753Smm}
454