test_write_disk_perms.c revision 228759
1151912Sphk/*-
2151912Sphk * Copyright (c) 2003-2007 Tim Kientzle
3209440Smav * All rights reserved.
4151912Sphk *
5151912Sphk * Redistribution and use in source and binary forms, with or without
6151912Sphk * modification, are permitted provided that the following conditions
7151912Sphk * are met:
8151912Sphk * 1. Redistributions of source code must retain the above copyright
9151912Sphk *    notice, this list of conditions and the following disclaimer.
10151912Sphk * 2. Redistributions in binary form must reproduce the above copyright
11151912Sphk *    notice, this list of conditions and the following disclaimer in the
12151912Sphk *    documentation and/or other materials provided with the distribution.
13151912Sphk *
14151912Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15151912Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16151912Sphk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17151912Sphk * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18151912Sphk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19151912Sphk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20151912Sphk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21151912Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22151912Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23151912Sphk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24151912Sphk */
25151912Sphk#include "test.h"
26151912Sphk__FBSDID("$FreeBSD: head/lib/libarchive/test/test_write_disk_perms.c 201247 2009-12-30 05:59:21Z kientzle $");
27151912Sphk
28151912Sphk#if ARCHIVE_VERSION_NUMBER >= 1009000 && (!defined(_WIN32) || defined(__CYGWIN__))
29151912Sphk
30151912Sphk#define UMASK 022
31151912Sphk
32268351Smarcelstatic long _default_gid = -1;
33209371Smavstatic long _invalid_gid = -1;
34209371Smavstatic long _alt_gid = -1;
35209371Smav
36209371Smav/*
37151912Sphk * To fully test SGID restores, we need three distinct GIDs to work
38273598Srpaulo * with:
39159217Snjl *    * the GID that files are created with by default (for the
40151912Sphk *      current user in the current directory)
41151912Sphk *    * An "alt gid" that this user can create files with
42209371Smav *    * An "invalid gid" that this user is not permitted to create
43151912Sphk *      files with.
44273598Srpaulo * The second fails if this user doesn't belong to at least two groups;
45151912Sphk * the third fails if the current user is root.
46209371Smav */
47209371Smavstatic void
48209371Smavsearchgid(void)
49151912Sphk{
50159217Snjl	static int   _searched = 0;
51193530Sjkim	uid_t uid = getuid();
52193530Sjkim	gid_t gid = 0;
53193530Sjkim	unsigned int n;
54151912Sphk	struct stat st;
55175385Sjhb	int fd;
56151912Sphk
57209371Smav	/* If we've already looked this up, we're done. */
58209371Smav	if (_searched)
59209371Smav		return;
60209371Smav	_searched = 1;
61203062Savg
62240286Smav	/* Create a file on disk in the current default dir. */
63203062Savg	fd = open("test_gid", O_CREAT | O_BINARY, 0664);
64213302Smav	failure("Couldn't create a file for gid testing.");
65232797Smav	assert(fd > 0);
66203062Savg
67151912Sphk	/* See what GID it ended up with.  This is our "valid" GID. */
68151912Sphk	assert(fstat(fd, &st) == 0);
69209371Smav	_default_gid = st.st_gid;
70169574Stakawata
71151931Sscottl	/* Find a GID for which fchown() fails.  This is our "invalid" GID. */
72151935Sscottl	_invalid_gid = -1;
73151931Sscottl	/* This loop stops when we wrap the gid or examine 10,000 gids. */
74151931Sscottl	for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
75209371Smav		if (fchown(fd, uid, gid) != 0) {
76151912Sphk			_invalid_gid = gid;
77209371Smav			break;
78209371Smav		}
79209371Smav	}
80209371Smav
81209440Smav	/*
82212533Smav	 * Find a GID for which fchown() succeeds, but which isn't the
83212238Smav	 * default.  This is the "alternate" gid.
84159217Snjl	 */
85209371Smav	_alt_gid = -1;
86209371Smav	for (gid = 0, n = 0; gid == n && n < 10000 ; n++, gid++) {
87151912Sphk		/* _alt_gid must be different than _default_gid */
88209371Smav		if (gid == (gid_t)_default_gid)
89209440Smav			continue;
90209371Smav		if (fchown(fd, uid, gid) == 0) {
91209371Smav			_alt_gid = gid;
92209371Smav			break;
93209371Smav		}
94209371Smav	}
95209371Smav	close(fd);
96209371Smav}
97209371Smav
98212323Smavstatic int
99212323Smavaltgid(void)
100209371Smav{
101209371Smav	searchgid();
102209371Smav	return (_alt_gid);
103209371Smav}
104209371Smav
105209371Smavstatic int
106209371Smavinvalidgid(void)
107212491Smav{
108209371Smav	searchgid();
109209371Smav	return (_invalid_gid);
110209371Smav}
111273598Srpaulo
112273598Srpaulostatic int
113273598Srpaulodefaultgid(void)
114273598Srpaulo{
115151912Sphk	searchgid();
116151912Sphk	return (_default_gid);
117273598Srpaulo}
118273598Srpaulo#endif
119273598Srpaulo
120273598Srpaulo/*
121273598Srpaulo * Exercise permission and ownership restores.
122273598Srpaulo * In particular, try to exercise a bunch of border cases related
123273598Srpaulo * to files/dirs that already exist, SUID/SGID bits, etc.
124273598Srpaulo */
125273598Srpaulo
126273598SrpauloDEFINE_TEST(test_write_disk_perms)
127273598Srpaulo{
128273598Srpaulo#if ARCHIVE_VERSION_NUMBER < 1009000 || (defined(_WIN32) && !defined(__CYGWIN__))
129273598Srpaulo	skipping("archive_write_disk interface");
130159217Snjl#else
131209371Smav	struct archive *a;
132151912Sphk	struct archive_entry *ae;
133159217Snjl	struct stat st;
134159217Snjl
135269515Sroyger	assertUmask(UMASK);
136269515Sroyger
137269515Sroyger	/*
138159217Snjl	 * Set ownership of the current directory to the group of this
139151912Sphk	 * process.  Otherwise, the SGID tests below fail if the
140151912Sphk	 * /tmp directory is owned by a group to which we don't belong
141209371Smav	 * and we're on a system where group ownership is inherited.
142151912Sphk	 * (Because we're not allowed to SGID files with defaultgid().)
143151912Sphk	 */
144175385Sjhb	assertEqualInt(0, chown(".", getuid(), getgid()));
145151912Sphk
146151912Sphk	/* Create an archive_write_disk object. */
147175361Sjhb	assert((a = archive_write_disk_new()) != NULL);
148209371Smav
149175361Sjhb	/* Write a regular file to it. */
150175361Sjhb	assert((ae = archive_entry_new()) != NULL);
151175385Sjhb	archive_entry_copy_pathname(ae, "file_0755");
152175385Sjhb	archive_entry_set_mode(ae, S_IFREG | 0777);
153209440Smav	assert(0 == archive_write_header(a, ae));
154209440Smav	assert(0 == archive_write_finish_entry(a));
155209440Smav	archive_entry_free(ae);
156209440Smav
157185103Sjkim	/* Write a regular file, then write over it. */
158185103Sjkim	/* For files, the perms should get updated. */
159175361Sjhb	assert((ae = archive_entry_new()) != NULL);
160175361Sjhb	archive_entry_copy_pathname(ae, "file_overwrite_0144");
161175361Sjhb	archive_entry_set_mode(ae, S_IFREG | 0777);
162209371Smav	assert(0 == archive_write_header(a, ae));
163175361Sjhb	archive_entry_free(ae);
164175361Sjhb	assert(0 == archive_write_finish_entry(a));
165175385Sjhb	/* Check that file was created with different perms. */
166175385Sjhb	assert(0 == stat("file_overwrite_0144", &st));
167185103Sjkim	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
168185103Sjkim	assert((st.st_mode & 07777) != 0144);
169175361Sjhb	/* Overwrite, this should change the perms. */
170175361Sjhb	assert((ae = archive_entry_new()) != NULL);
171209371Smav	archive_entry_copy_pathname(ae, "file_overwrite_0144");
172247463Smav	archive_entry_set_mode(ae, S_IFREG | 0144);
173209371Smav	assert(0 == archive_write_header(a, ae));
174209371Smav	archive_entry_free(ae);
175209371Smav	assert(0 == archive_write_finish_entry(a));
176209371Smav
177212491Smav	/* Write a regular dir. */
178209371Smav	assert((ae = archive_entry_new()) != NULL);
179209371Smav	archive_entry_copy_pathname(ae, "dir_0514");
180247463Smav	archive_entry_set_mode(ae, S_IFDIR | 0514);
181209371Smav	assert(0 == archive_write_header(a, ae));
182247463Smav	archive_entry_free(ae);
183209371Smav	assert(0 == archive_write_finish_entry(a));
184209371Smav
185209371Smav	/* Overwrite an existing dir. */
186209371Smav	/* For dir, the first perms should get left. */
187247463Smav	assertMakeDir("dir_overwrite_0744", 0744);
188247463Smav	/* Check original perms. */
189247463Smav	assert(0 == stat("dir_overwrite_0744", &st));
190210290Smav	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
191212238Smav	assert((st.st_mode & 0777) == 0744);
192212238Smav	/* Overwrite shouldn't edit perms. */
193212238Smav	assert((ae = archive_entry_new()) != NULL);
194212491Smav	archive_entry_copy_pathname(ae, "dir_overwrite_0744");
195212238Smav	archive_entry_set_mode(ae, S_IFDIR | 0777);
196212491Smav	assert(0 == archive_write_header(a, ae));
197209371Smav	archive_entry_free(ae);
198209371Smav	assert(0 == archive_write_finish_entry(a));
199209371Smav	/* Make sure they're unchanged. */
200209371Smav	assert(0 == stat("dir_overwrite_0744", &st));
201212491Smav	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
202212491Smav	assert((st.st_mode & 0777) == 0744);
203212491Smav
204212491Smav	/* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
205209371Smav	assert((ae = archive_entry_new()) != NULL);
206212238Smav	archive_entry_copy_pathname(ae, "file_no_suid");
207212491Smav	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777);
208212491Smav	archive_write_disk_set_options(a, 0);
209212491Smav	assert(0 == archive_write_header(a, ae));
210212491Smav	assert(0 == archive_write_finish_entry(a));
211209371Smav
212224919Smav	/* Write a regular file with ARCHIVE_EXTRACT_PERM. */
213224919Smav	assert(archive_entry_clear(ae) != NULL);
214224919Smav	archive_entry_copy_pathname(ae, "file_0777");
215224919Smav	archive_entry_set_mode(ae, S_IFREG | 0777);
216212238Smav	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
217209371Smav	assert(0 == archive_write_header(a, ae));
218209371Smav	assert(0 == archive_write_finish_entry(a));
219209371Smav
220209371Smav	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */
221209371Smav	assert(archive_entry_clear(ae) != NULL);
222209371Smav	archive_entry_copy_pathname(ae, "file_4742");
223209371Smav	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
224209371Smav	archive_entry_set_uid(ae, getuid());
225209371Smav	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
226209371Smav	assert(0 == archive_write_header(a, ae));
227209371Smav	assert(0 == archive_write_finish_entry(a));
228209371Smav
229209371Smav	/*
230209371Smav	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit,
231209371Smav	 * but wrong uid.  POSIX says you shouldn't restore SUID bit
232209371Smav	 * unless the UID could be restored.
233209371Smav	 */
234209371Smav	assert(archive_entry_clear(ae) != NULL);
235209371Smav	archive_entry_copy_pathname(ae, "file_bad_suid");
236209371Smav	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
237209371Smav	archive_entry_set_uid(ae, getuid() + 1);
238209371Smav	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
239209371Smav	assertA(0 == archive_write_header(a, ae));
240209371Smav	/*
241209371Smav	 * Because we didn't ask for owner, the failure to
242212491Smav	 * restore SUID shouldn't return a failure.
243212491Smav	 * We check below to make sure SUID really wasn't set.
244212323Smav	 * See more detailed comments below.
245212323Smav	 */
246212323Smav	failure("Opportunistic SUID failure shouldn't return error.");
247212323Smav	assertEqualInt(0, archive_write_finish_entry(a));
248212323Smav
249212323Smav        if (getuid() != 0) {
250212323Smav		assert(archive_entry_clear(ae) != NULL);
251212323Smav		archive_entry_copy_pathname(ae, "file_bad_suid2");
252212323Smav		archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
253212323Smav		archive_entry_set_uid(ae, getuid() + 1);
254212323Smav		archive_write_disk_set_options(a,
255212323Smav		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
256212323Smav		assertA(0 == archive_write_header(a, ae));
257212323Smav		/* Owner change should fail here. */
258212491Smav		failure("Non-opportunistic SUID failure should return error.");
259212491Smav		assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
260212323Smav	}
261212491Smav
262212323Smav	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
263212323Smav	assert(archive_entry_clear(ae) != NULL);
264212323Smav	archive_entry_copy_pathname(ae, "file_perm_sgid");
265209371Smav	archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
266209371Smav	archive_entry_set_gid(ae, defaultgid());
267212491Smav	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
268209371Smav	assert(0 == archive_write_header(a, ae));
269212491Smav	failure("Setting SGID bit should succeed here.");
270212491Smav	assertEqualIntA(a, 0, archive_write_finish_entry(a));
271209371Smav
272212491Smav	if (altgid() == -1) {
273209371Smav		/*
274209371Smav		 * Current user must belong to at least two groups or
275209371Smav		 * else we can't test setting the GID to another group.
276209990Smav		 */
277209990Smav		skipping("Current user can't test gid restore: must belong to more than one group.");
278209371Smav	} else {
279209371Smav		/*
280209371Smav		 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit
281209371Smav		 * but without ARCHIVE_EXTRACT_OWNER.
282209371Smav		 */
283209371Smav		/*
284209371Smav		 * This is a weird case: The user has asked for permissions to
285209371Smav		 * be restored but not asked for ownership to be restored.  As
286209371Smav		 * a result, the default file creation will create a file with
287209371Smav		 * the wrong group.  There are several possible behaviors for
288209371Smav		 * libarchive in this scenario:
289209371Smav		 *  = Set the SGID bit.  It is wrong and a security hole to
290209371Smav		 *    set SGID with the wrong group.  Even POSIX thinks so.
291209371Smav		 *  = Implicitly set the group.  I don't like this.
292209371Smav		 *  = drop the SGID bit and warn (the old libarchive behavior)
293209371Smav		 *  = drop the SGID bit and don't warn (the current libarchive
294209371Smav		 *    behavior).
295209371Smav		 * The current behavior sees SGID/SUID restore when you
296209371Smav		 * don't ask for owner restore as an "opportunistic"
297209371Smav		 * action.  That is, libarchive should do it if it can,
298209371Smav		 * but if it can't, it's not an error.
299209371Smav		 */
300209371Smav		assert(archive_entry_clear(ae) != NULL);
301209371Smav		archive_entry_copy_pathname(ae, "file_alt_sgid");
302208436Smav		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
303209371Smav		archive_entry_set_uid(ae, getuid());
304208436Smav		archive_entry_set_gid(ae, altgid());
305208436Smav		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
306208436Smav		assert(0 == archive_write_header(a, ae));
307208436Smav		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.");
308208438Smav		assertEqualIntA(a, 0, archive_write_finish_entry(a));
309208436Smav
310208436Smav		/*
311208436Smav		 * As above, but add _EXTRACT_OWNER to verify that it
312208436Smav		 * does succeed.
313208436Smav		 */
314208436Smav		assert(archive_entry_clear(ae) != NULL);
315208436Smav		archive_entry_copy_pathname(ae, "file_alt_sgid_owner");
316209371Smav		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
317209371Smav		archive_entry_set_uid(ae, getuid());
318258164Smav		archive_entry_set_gid(ae, altgid());
319208436Smav		archive_write_disk_set_options(a,
320208436Smav		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
321208436Smav		assert(0 == archive_write_header(a, ae));
322216263Sjhb		failure("Setting SGID bit should succeed here.");
323216263Sjhb		assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
324216263Sjhb	}
325216263Sjhb
326216263Sjhb	/*
327216263Sjhb	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit,
328216263Sjhb	 * but wrong GID.  POSIX says you shouldn't restore SGID bit
329216263Sjhb	 * unless the GID could be restored.
330216263Sjhb	 */
331216263Sjhb	if (invalidgid() == -1) {
332216263Sjhb		/* This test always fails for root. */
333216263Sjhb		printf("Running as root: Can't test SGID failures.\n");
334216263Sjhb	} else {
335216263Sjhb		assert(archive_entry_clear(ae) != NULL);
336216263Sjhb		archive_entry_copy_pathname(ae, "file_bad_sgid");
337216263Sjhb		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
338216263Sjhb		archive_entry_set_gid(ae, invalidgid());
339273598Srpaulo		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
340273598Srpaulo		assertA(0 == archive_write_header(a, ae));
341273598Srpaulo		failure("This SGID restore should fail without an error.");
342273598Srpaulo		assertEqualIntA(a, 0, archive_write_finish_entry(a));
343273598Srpaulo
344273598Srpaulo		assert(archive_entry_clear(ae) != NULL);
345273598Srpaulo		archive_entry_copy_pathname(ae, "file_bad_sgid2");
346273598Srpaulo		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
347273598Srpaulo		archive_entry_set_gid(ae, invalidgid());
348273598Srpaulo		archive_write_disk_set_options(a,
349273598Srpaulo		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
350273598Srpaulo		assertA(0 == archive_write_header(a, ae));
351273598Srpaulo		failure("This SGID restore should fail with an error.");
352273598Srpaulo		assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
353273598Srpaulo	}
354273598Srpaulo
355273598Srpaulo	/* Set ownership should fail if we're not root. */
356273598Srpaulo	if (getuid() == 0) {
357273598Srpaulo		printf("Running as root: Can't test setuid failures.\n");
358273598Srpaulo	} else {
359273598Srpaulo		assert(archive_entry_clear(ae) != NULL);
360273598Srpaulo		archive_entry_copy_pathname(ae, "file_bad_owner");
361273598Srpaulo		archive_entry_set_mode(ae, S_IFREG | 0744);
362273598Srpaulo		archive_entry_set_uid(ae, getuid() + 1);
363273598Srpaulo		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER);
364273598Srpaulo		assertA(0 == archive_write_header(a, ae));
365273598Srpaulo		assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a));
366273598Srpaulo	}
367273598Srpaulo
368273598Srpaulo#if ARCHIVE_VERSION_NUMBER < 2000000
369273598Srpaulo	archive_write_finish(a);
370273598Srpaulo#else
371273598Srpaulo	assert(0 == archive_write_finish(a));
372273598Srpaulo#endif
373273598Srpaulo	archive_entry_free(ae);
374273598Srpaulo
375273598Srpaulo	/* Test the entries on disk. */
376273598Srpaulo	assert(0 == stat("file_0755", &st));
377273598Srpaulo	failure("file_0755: st.st_mode=%o", st.st_mode);
378273598Srpaulo	assert((st.st_mode & 07777) == 0755);
379273598Srpaulo
380169592Snjl	assert(0 == stat("file_overwrite_0144", &st));
381172489Snjl	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
382209371Smav	assert((st.st_mode & 07777) == 0144);
383169574Stakawata
384169574Stakawata	assert(0 == stat("dir_0514", &st));
385169574Stakawata	failure("dir_0514: st.st_mode=%o", st.st_mode);
386169574Stakawata	assert((st.st_mode & 07777) == 0514);
387258164Smav
388169574Stakawata	assert(0 == stat("dir_overwrite_0744", &st));
389172489Snjl	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
390209371Smav	assert((st.st_mode & 0777) == 0744);
391172489Snjl
392208436Smav	assert(0 == stat("file_no_suid", &st));
393208436Smav	failure("file_0755: st.st_mode=%o", st.st_mode);
394208436Smav	assert((st.st_mode & 07777) == 0755);
395208436Smav
396208436Smav	assert(0 == stat("file_0777", &st));
397208436Smav	failure("file_0777: st.st_mode=%o", st.st_mode);
398258164Smav	assert((st.st_mode & 07777) == 0777);
399208436Smav
400258164Smav	/* SUID bit should get set here. */
401258164Smav	assert(0 == stat("file_4742", &st));
402208436Smav	failure("file_4742: st.st_mode=%o", st.st_mode);
403258164Smav	assert((st.st_mode & 07777) == (S_ISUID | 0742));
404258164Smav
405258164Smav	/* SUID bit should NOT have been set here. */
406258164Smav	assert(0 == stat("file_bad_suid", &st));
407258164Smav	failure("file_bad_suid: st.st_mode=%o", st.st_mode);
408208436Smav	assert((st.st_mode & 07777) == (0742));
409258164Smav
410208436Smav	/* Some things don't fail if you're root, so suppress this. */
411231161Sjkim	if (getuid() != 0) {
412208436Smav		/* SUID bit should NOT have been set here. */
413208436Smav		assert(0 == stat("file_bad_suid2", &st));
414208436Smav		failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
415208436Smav		assert((st.st_mode & 07777) == (0742));
416208436Smav	}
417208436Smav
418169574Stakawata	/* SGID should be set here. */
419169574Stakawata	assert(0 == stat("file_perm_sgid", &st));
420169574Stakawata	failure("file_perm_sgid: st.st_mode=%o", st.st_mode);
421151912Sphk	assert((st.st_mode & 07777) == (S_ISGID | 0742));
422209371Smav
423151912Sphk	if (altgid() != -1) {
424159217Snjl		/* SGID should not be set here. */
425159217Snjl		assert(0 == stat("file_alt_sgid", &st));
426269515Sroyger		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
427151912Sphk		assert((st.st_mode & 07777) == (0742));
428199016Savg
429208436Smav		/* SGID should be set here. */
430169592Snjl		assert(0 == stat("file_alt_sgid_owner", &st));
431151912Sphk		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
432159217Snjl		assert((st.st_mode & 07777) == (S_ISGID | 0742));
433151912Sphk	}
434151912Sphk
435151912Sphk	if (invalidgid() != -1) {
436151912Sphk		/* SGID should NOT be set here. */
437209371Smav		assert(0 == stat("file_bad_sgid", &st));
438151912Sphk		failure("file_bad_sgid: st.st_mode=%o", st.st_mode);
439209371Smav		assert((st.st_mode & 07777) == (0742));
440209371Smav		/* SGID should NOT be set here. */
441209371Smav		assert(0 == stat("file_bad_sgid2", &st));
442209371Smav		failure("file_bad_sgid2: st.st_mode=%o", st.st_mode);
443209371Smav		assert((st.st_mode & 07777) == (0742));
444212238Smav	}
445209371Smav
446151912Sphk	if (getuid() != 0) {
447151912Sphk		assert(0 == stat("file_bad_owner", &st));
448151912Sphk		failure("file_bad_owner: st.st_mode=%o", st.st_mode);
449151912Sphk		assert((st.st_mode & 07777) == (0744));
450151912Sphk		failure("file_bad_owner: st.st_uid=%d getuid()=%d",
451151912Sphk		    st.st_uid, getuid());
452151912Sphk		/* The entry had getuid()+1, but because we're
453209371Smav		 * not root, we should not have been able to set that. */
454209371Smav		assert(st.st_uid == getuid());
455159217Snjl	}
456159217Snjl#endif
457159217Snjl}
458151912Sphk