test_write_disk_perms.c revision 232153
18876Srgrimes/*-
24Srgrimes * Copyright (c) 2003-2007 Tim Kientzle
34Srgrimes * All rights reserved.
44Srgrimes *
58876Srgrimes * Redistribution and use in source and binary forms, with or without
64Srgrimes * modification, are permitted provided that the following conditions
74Srgrimes * are met:
84Srgrimes * 1. Redistributions of source code must retain the above copyright
94Srgrimes *    notice, this list of conditions and the following disclaimer.
104Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
118876Srgrimes *    notice, this list of conditions and the following disclaimer in the
128876Srgrimes *    documentation and/or other materials provided with the distribution.
134Srgrimes *
144Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
158876Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
164Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
178876Srgrimes * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
184Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
194Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
204Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
214Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228876Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
234Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
244Srgrimes */
254Srgrimes#include "test.h"
2617495Sjoerg__FBSDID("$FreeBSD: head/contrib/libarchive/libarchive/test/test_write_disk_perms.c 232153 2012-02-25 10:58:02Z mm $");
274Srgrimes
28623Srgrimes#if !defined(_WIN32) || defined(__CYGWIN__)
294Srgrimes
304Srgrimes#define UMASK 022
314Srgrimes
324Srgrimesstatic long _default_gid = -1;
334Srgrimesstatic long _invalid_gid = -1;
342056Swollmanstatic long _alt_gid = -1;
3517495Sjoerg
362056Swollman/*
3712734Sbde * To fully test SGID restores, we need three distinct GIDs to work
3812734Sbde * with:
3912734Sbde *    * the GID that files are created with by default (for the
402056Swollman *      current user in the current directory)
412056Swollman *    * An "alt gid" that this user can create files with
424Srgrimes *    * An "invalid gid" that this user is not permitted to create
434Srgrimes *      files with.
444Srgrimes * The second fails if this user doesn't belong to at least two groups;
454Srgrimes * the third fails if the current user is root.
464Srgrimes */
474Srgrimesstatic void
484Srgrimessearchgid(void)
494Srgrimes{
504Srgrimes	static int   _searched = 0;
514Srgrimes	uid_t uid = getuid();
5212720Sphk	gid_t gid = 0;
5312720Sphk	unsigned int n;
5412720Sphk	struct stat st;
5512720Sphk	int fd;
564Srgrimes
5717495Sjoerg	/* If we've already looked this up, we're done. */
5817495Sjoerg	if (_searched)
5917495Sjoerg		return;
6017495Sjoerg	_searched = 1;
6117495Sjoerg
6217495Sjoerg	/* Create a file on disk in the current default dir. */
6317495Sjoerg	fd = open("test_gid", O_CREAT | O_BINARY, 0664);
644Srgrimes	failure("Couldn't create a file for gid testing.");
654Srgrimes	assert(fd > 0);
664Srgrimes
674Srgrimes	/* See what GID it ended up with.  This is our "valid" GID. */
684Srgrimes	assert(fstat(fd, &st) == 0);
6912515Sphk	_default_gid = st.st_gid;
7012515Sphk
7112515Sphk	/* Find a GID for which fchown() fails.  This is our "invalid" GID. */
7212515Sphk	_invalid_gid = -1;
7312515Sphk	/* This loop stops when we wrap the gid or examine 10,000 gids. */
7412473Sbde	for (gid = 1, n = 1; gid == n && n < 10000 ; n++, gid++) {
754Srgrimes		if (fchown(fd, uid, gid) != 0) {
764Srgrimes			_invalid_gid = gid;
774Srgrimes			break;
784Srgrimes		}
794Srgrimes	}
804Srgrimes
814Srgrimes	/*
824Srgrimes	 * Find a GID for which fchown() succeeds, but which isn't the
834Srgrimes	 * default.  This is the "alternate" gid.
844Srgrimes	 */
854Srgrimes	_alt_gid = -1;
864Srgrimes	for (gid = 0, n = 0; gid == n && n < 10000 ; n++, gid++) {
874Srgrimes		/* _alt_gid must be different than _default_gid */
884Srgrimes		if (gid == (gid_t)_default_gid)
894Srgrimes			continue;
904Srgrimes		if (fchown(fd, uid, gid) == 0) {
914Srgrimes			_alt_gid = gid;
924Srgrimes			break;
934Srgrimes		}
944Srgrimes	}
954Srgrimes	close(fd);
964Srgrimes}
974Srgrimes
984Srgrimesstatic int
994Srgrimesaltgid(void)
1004Srgrimes{
1014Srgrimes	searchgid();
1024Srgrimes	return (_alt_gid);
1034Srgrimes}
1044Srgrimes
1054Srgrimesstatic int
1064Srgrimesinvalidgid(void)
1074Srgrimes{
1084Srgrimes	searchgid();
1094Srgrimes	return (_invalid_gid);
1104Srgrimes}
1114Srgrimes
1124Srgrimesstatic int
1134Srgrimesdefaultgid(void)
1144Srgrimes{
1154Srgrimes	searchgid();
1164Srgrimes	return (_default_gid);
1174Srgrimes}
1184Srgrimes#endif
1194Srgrimes
1204Srgrimes/*
1214Srgrimes * Exercise permission and ownership restores.
1224Srgrimes * In particular, try to exercise a bunch of border cases related
1234Srgrimes * to files/dirs that already exist, SUID/SGID bits, etc.
1244Srgrimes */
1254Srgrimes
1264SrgrimesDEFINE_TEST(test_write_disk_perms)
1274Srgrimes{
1284Srgrimes#if defined(_WIN32) && !defined(__CYGWIN__)
1294Srgrimes	skipping("archive_write_disk interface");
1304Srgrimes#else
1314Srgrimes	struct archive *a;
1324Srgrimes	struct archive_entry *ae;
1334Srgrimes	struct stat st;
1344Srgrimes
1354Srgrimes	assertUmask(UMASK);
1364Srgrimes
1374Srgrimes	/*
1384Srgrimes	 * Set ownership of the current directory to the group of this
1394Srgrimes	 * process.  Otherwise, the SGID tests below fail if the
1404Srgrimes	 * /tmp directory is owned by a group to which we don't belong
1414Srgrimes	 * and we're on a system where group ownership is inherited.
1424Srgrimes	 * (Because we're not allowed to SGID files with defaultgid().)
1434Srgrimes	 */
1444Srgrimes	assertEqualInt(0, chown(".", getuid(), getgid()));
1454Srgrimes
1464Srgrimes	/* Create an archive_write_disk object. */
1474Srgrimes	assert((a = archive_write_disk_new()) != NULL);
1484Srgrimes
1494Srgrimes	/* Write a regular file to it. */
1504Srgrimes	assert((ae = archive_entry_new()) != NULL);
1514Srgrimes	archive_entry_copy_pathname(ae, "file_0755");
1524Srgrimes	archive_entry_set_mode(ae, S_IFREG | 0777);
1534Srgrimes	assert(0 == archive_write_header(a, ae));
1544Srgrimes	assert(0 == archive_write_finish_entry(a));
1554Srgrimes	archive_entry_free(ae);
1564Srgrimes
1574Srgrimes	/* Write a regular file, then write over it. */
1584Srgrimes	/* For files, the perms should get updated. */
1594Srgrimes	assert((ae = archive_entry_new()) != NULL);
1604Srgrimes	archive_entry_copy_pathname(ae, "file_overwrite_0144");
1614Srgrimes	archive_entry_set_mode(ae, S_IFREG | 0777);
1624Srgrimes	assert(0 == archive_write_header(a, ae));
1634Srgrimes	archive_entry_free(ae);
1644Srgrimes	assert(0 == archive_write_finish_entry(a));
1654Srgrimes	/* Check that file was created with different perms. */
1664Srgrimes	assert(0 == stat("file_overwrite_0144", &st));
1674Srgrimes	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
1684Srgrimes	assert((st.st_mode & 07777) != 0144);
1694Srgrimes	/* Overwrite, this should change the perms. */
1704Srgrimes	assert((ae = archive_entry_new()) != NULL);
1714Srgrimes	archive_entry_copy_pathname(ae, "file_overwrite_0144");
1724Srgrimes	archive_entry_set_mode(ae, S_IFREG | 0144);
1734Srgrimes	assert(0 == archive_write_header(a, ae));
1744Srgrimes	archive_entry_free(ae);
1754Srgrimes	assert(0 == archive_write_finish_entry(a));
1764Srgrimes
1774Srgrimes	/* Write a regular dir. */
1784Srgrimes	assert((ae = archive_entry_new()) != NULL);
1794Srgrimes	archive_entry_copy_pathname(ae, "dir_0514");
1804Srgrimes	archive_entry_set_mode(ae, S_IFDIR | 0514);
1814Srgrimes	assert(0 == archive_write_header(a, ae));
18217495Sjoerg	archive_entry_free(ae);
1834Srgrimes	assert(0 == archive_write_finish_entry(a));
1844Srgrimes
1854Srgrimes	/* Overwrite an existing dir. */
1864Srgrimes	/* For dir, the first perms should get left. */
1874Srgrimes	assertMakeDir("dir_overwrite_0744", 0744);
18817495Sjoerg	/* Check original perms. */
18917495Sjoerg	assert(0 == stat("dir_overwrite_0744", &st));
19017495Sjoerg	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
19117495Sjoerg	assert((st.st_mode & 0777) == 0744);
19217495Sjoerg	/* Overwrite shouldn't edit perms. */
19317495Sjoerg	assert((ae = archive_entry_new()) != NULL);
19417495Sjoerg	archive_entry_copy_pathname(ae, "dir_overwrite_0744");
19517495Sjoerg	archive_entry_set_mode(ae, S_IFDIR | 0777);
19617495Sjoerg	assert(0 == archive_write_header(a, ae));
19717495Sjoerg	archive_entry_free(ae);
19817495Sjoerg	assert(0 == archive_write_finish_entry(a));
19917495Sjoerg	/* Make sure they're unchanged. */
20017495Sjoerg	assert(0 == stat("dir_overwrite_0744", &st));
20117495Sjoerg	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
20217495Sjoerg	assert((st.st_mode & 0777) == 0744);
20317495Sjoerg
20417495Sjoerg	/* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */
20517495Sjoerg	assert((ae = archive_entry_new()) != NULL);
20617495Sjoerg	archive_entry_copy_pathname(ae, "file_no_suid");
20717495Sjoerg	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777);
20817495Sjoerg	archive_write_disk_set_options(a, 0);
20917495Sjoerg	assert(0 == archive_write_header(a, ae));
21017495Sjoerg	assert(0 == archive_write_finish_entry(a));
21117495Sjoerg
21217495Sjoerg	/* Write a regular file with ARCHIVE_EXTRACT_PERM. */
21317495Sjoerg	assert(archive_entry_clear(ae) != NULL);
21417495Sjoerg	archive_entry_copy_pathname(ae, "file_0777");
21517495Sjoerg	archive_entry_set_mode(ae, S_IFREG | 0777);
21617495Sjoerg	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
21717495Sjoerg	assert(0 == archive_write_header(a, ae));
21817495Sjoerg	assert(0 == archive_write_finish_entry(a));
21917495Sjoerg
22017495Sjoerg	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */
22117495Sjoerg	assert(archive_entry_clear(ae) != NULL);
2224Srgrimes	archive_entry_copy_pathname(ae, "file_4742");
2234Srgrimes	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
2244Srgrimes	archive_entry_set_uid(ae, getuid());
2254Srgrimes	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
2264Srgrimes	assert(0 == archive_write_header(a, ae));
2274Srgrimes	assert(0 == archive_write_finish_entry(a));
2284Srgrimes
2294Srgrimes	/*
2304Srgrimes	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit,
2314Srgrimes	 * but wrong uid.  POSIX says you shouldn't restore SUID bit
2324Srgrimes	 * unless the UID could be restored.
2334Srgrimes	 */
2344Srgrimes	assert(archive_entry_clear(ae) != NULL);
2354Srgrimes	archive_entry_copy_pathname(ae, "file_bad_suid");
2364Srgrimes	archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
2374Srgrimes	archive_entry_set_uid(ae, getuid() + 1);
2384Srgrimes	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
2394Srgrimes	assertA(0 == archive_write_header(a, ae));
2404Srgrimes	/*
2414Srgrimes	 * Because we didn't ask for owner, the failure to
2424Srgrimes	 * restore SUID shouldn't return a failure.
2434Srgrimes	 * We check below to make sure SUID really wasn't set.
2444Srgrimes	 * See more detailed comments below.
2454Srgrimes	 */
2464Srgrimes	failure("Opportunistic SUID failure shouldn't return error.");
24712473Sbde	assertEqualInt(0, archive_write_finish_entry(a));
2482112Swollman
2492112Swollman        if (getuid() != 0) {
2502112Swollman		assert(archive_entry_clear(ae) != NULL);
2512112Swollman		archive_entry_copy_pathname(ae, "file_bad_suid2");
2522112Swollman		archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742);
2534Srgrimes		archive_entry_set_uid(ae, getuid() + 1);
2544Srgrimes		archive_write_disk_set_options(a,
2554Srgrimes		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
2564Srgrimes		assertA(0 == archive_write_header(a, ae));
25717495Sjoerg		/* Owner change should fail here. */
25817495Sjoerg		failure("Non-opportunistic SUID failure should return error.");
25917495Sjoerg		assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a));
26017495Sjoerg	}
26117495Sjoerg
26217495Sjoerg	/* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */
26317495Sjoerg	assert(archive_entry_clear(ae) != NULL);
26417495Sjoerg	archive_entry_copy_pathname(ae, "file_perm_sgid");
26517495Sjoerg	archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
26617495Sjoerg	archive_entry_set_gid(ae, defaultgid());
26717495Sjoerg	archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
26817495Sjoerg	assert(0 == archive_write_header(a, ae));
26917495Sjoerg	failure("Setting SGID bit should succeed here.");
27017495Sjoerg	assertEqualIntA(a, 0, archive_write_finish_entry(a));
2714Srgrimes
2724Srgrimes	if (altgid() == -1) {
2734Srgrimes		/*
2744Srgrimes		 * Current user must belong to at least two groups or
2754Srgrimes		 * else we can't test setting the GID to another group.
2764Srgrimes		 */
2774Srgrimes		skipping("Current user can't test gid restore: must belong to more than one group.");
2784Srgrimes	} else {
2794Srgrimes		/*
2804Srgrimes		 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit
28115680Sgpalmer		 * but without ARCHIVE_EXTRACT_OWNER.
28217495Sjoerg		 */
2834Srgrimes		/*
28417495Sjoerg		 * This is a weird case: The user has asked for permissions to
28517495Sjoerg		 * be restored but not asked for ownership to be restored.  As
28617495Sjoerg		 * a result, the default file creation will create a file with
28717495Sjoerg		 * the wrong group.  There are several possible behaviors for
28817495Sjoerg		 * libarchive in this scenario:
28917495Sjoerg		 *  = Set the SGID bit.  It is wrong and a security hole to
29017495Sjoerg		 *    set SGID with the wrong group.  Even POSIX thinks so.
29117495Sjoerg		 *  = Implicitly set the group.  I don't like this.
29217495Sjoerg		 *  = drop the SGID bit and warn (the old libarchive behavior)
29317495Sjoerg		 *  = drop the SGID bit and don't warn (the current libarchive
29417495Sjoerg		 *    behavior).
29517495Sjoerg		 * The current behavior sees SGID/SUID restore when you
2964Srgrimes		 * don't ask for owner restore as an "opportunistic"
2974Srgrimes		 * action.  That is, libarchive should do it if it can,
2984Srgrimes		 * but if it can't, it's not an error.
2994Srgrimes		 */
3004Srgrimes		assert(archive_entry_clear(ae) != NULL);
3014Srgrimes		archive_entry_copy_pathname(ae, "file_alt_sgid");
3024Srgrimes		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
3034Srgrimes		archive_entry_set_uid(ae, getuid());
3044Srgrimes		archive_entry_set_gid(ae, altgid());
3054Srgrimes		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
3064Srgrimes		assert(0 == archive_write_header(a, ae));
3074Srgrimes		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.");
3084Srgrimes		assertEqualIntA(a, 0, archive_write_finish_entry(a));
3094Srgrimes
3104Srgrimes		/*
3114Srgrimes		 * As above, but add _EXTRACT_OWNER to verify that it
3124Srgrimes		 * does succeed.
3134Srgrimes		 */
3144Srgrimes		assert(archive_entry_clear(ae) != NULL);
3154Srgrimes		archive_entry_copy_pathname(ae, "file_alt_sgid_owner");
3164Srgrimes		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
3174Srgrimes		archive_entry_set_uid(ae, getuid());
3184Srgrimes		archive_entry_set_gid(ae, altgid());
3194Srgrimes		archive_write_disk_set_options(a,
3204Srgrimes		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
3214Srgrimes		assert(0 == archive_write_header(a, ae));
3224Srgrimes		failure("Setting SGID bit should succeed here.");
3234Srgrimes		assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
3244Srgrimes	}
3254Srgrimes
3264Srgrimes	/*
3274Srgrimes	 * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit,
328798Swollman	 * but wrong GID.  POSIX says you shouldn't restore SGID bit
3294Srgrimes	 * unless the GID could be restored.
330798Swollman	 */
3314Srgrimes	if (invalidgid() == -1) {
3328876Srgrimes		/* This test always fails for root. */
333		printf("Running as root: Can't test SGID failures.\n");
334	} else {
335		assert(archive_entry_clear(ae) != NULL);
336		archive_entry_copy_pathname(ae, "file_bad_sgid");
337		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
338		archive_entry_set_gid(ae, invalidgid());
339		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM);
340		assertA(0 == archive_write_header(a, ae));
341		failure("This SGID restore should fail without an error.");
342		assertEqualIntA(a, 0, archive_write_finish_entry(a));
343
344		assert(archive_entry_clear(ae) != NULL);
345		archive_entry_copy_pathname(ae, "file_bad_sgid2");
346		archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742);
347		archive_entry_set_gid(ae, invalidgid());
348		archive_write_disk_set_options(a,
349		    ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER);
350		assertA(0 == archive_write_header(a, ae));
351		failure("This SGID restore should fail with an error.");
352		assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a));
353	}
354
355	/* Set ownership should fail if we're not root. */
356	if (getuid() == 0) {
357		printf("Running as root: Can't test setuid failures.\n");
358	} else {
359		assert(archive_entry_clear(ae) != NULL);
360		archive_entry_copy_pathname(ae, "file_bad_owner");
361		archive_entry_set_mode(ae, S_IFREG | 0744);
362		archive_entry_set_uid(ae, getuid() + 1);
363		archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER);
364		assertA(0 == archive_write_header(a, ae));
365		assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a));
366	}
367
368	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
369	archive_entry_free(ae);
370
371	/* Test the entries on disk. */
372	assert(0 == stat("file_0755", &st));
373	failure("file_0755: st.st_mode=%o", st.st_mode);
374	assert((st.st_mode & 07777) == 0755);
375
376	assert(0 == stat("file_overwrite_0144", &st));
377	failure("file_overwrite_0144: st.st_mode=%o", st.st_mode);
378	assert((st.st_mode & 07777) == 0144);
379
380	assert(0 == stat("dir_0514", &st));
381	failure("dir_0514: st.st_mode=%o", st.st_mode);
382	assert((st.st_mode & 07777) == 0514);
383
384	assert(0 == stat("dir_overwrite_0744", &st));
385	failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode);
386	assert((st.st_mode & 0777) == 0744);
387
388	assert(0 == stat("file_no_suid", &st));
389	failure("file_0755: st.st_mode=%o", st.st_mode);
390	assert((st.st_mode & 07777) == 0755);
391
392	assert(0 == stat("file_0777", &st));
393	failure("file_0777: st.st_mode=%o", st.st_mode);
394	assert((st.st_mode & 07777) == 0777);
395
396	/* SUID bit should get set here. */
397	assert(0 == stat("file_4742", &st));
398	failure("file_4742: st.st_mode=%o", st.st_mode);
399	assert((st.st_mode & 07777) == (S_ISUID | 0742));
400
401	/* SUID bit should NOT have been set here. */
402	assert(0 == stat("file_bad_suid", &st));
403	failure("file_bad_suid: st.st_mode=%o", st.st_mode);
404	assert((st.st_mode & 07777) == (0742));
405
406	/* Some things don't fail if you're root, so suppress this. */
407	if (getuid() != 0) {
408		/* SUID bit should NOT have been set here. */
409		assert(0 == stat("file_bad_suid2", &st));
410		failure("file_bad_suid2: st.st_mode=%o", st.st_mode);
411		assert((st.st_mode & 07777) == (0742));
412	}
413
414	/* SGID should be set here. */
415	assert(0 == stat("file_perm_sgid", &st));
416	failure("file_perm_sgid: st.st_mode=%o", st.st_mode);
417	assert((st.st_mode & 07777) == (S_ISGID | 0742));
418
419	if (altgid() != -1) {
420		/* SGID should not be set here. */
421		assert(0 == stat("file_alt_sgid", &st));
422		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
423		assert((st.st_mode & 07777) == (0742));
424
425		/* SGID should be set here. */
426		assert(0 == stat("file_alt_sgid_owner", &st));
427		failure("file_alt_sgid: st.st_mode=%o", st.st_mode);
428		assert((st.st_mode & 07777) == (S_ISGID | 0742));
429	}
430
431	if (invalidgid() != -1) {
432		/* SGID should NOT be set here. */
433		assert(0 == stat("file_bad_sgid", &st));
434		failure("file_bad_sgid: st.st_mode=%o", st.st_mode);
435		assert((st.st_mode & 07777) == (0742));
436		/* SGID should NOT be set here. */
437		assert(0 == stat("file_bad_sgid2", &st));
438		failure("file_bad_sgid2: st.st_mode=%o", st.st_mode);
439		assert((st.st_mode & 07777) == (0742));
440	}
441
442	if (getuid() != 0) {
443		assert(0 == stat("file_bad_owner", &st));
444		failure("file_bad_owner: st.st_mode=%o", st.st_mode);
445		assert((st.st_mode & 07777) == (0744));
446		failure("file_bad_owner: st.st_uid=%d getuid()=%d",
447		    st.st_uid, getuid());
448		/* The entry had getuid()+1, but because we're
449		 * not root, we should not have been able to set that. */
450		assert(st.st_uid == getuid());
451	}
452#endif
453}
454