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: stable/10/contrib/libarchive/libarchive/test/test_write_disk_perms.c 328828 2018-02-03 02:17:25Z mm $"); 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; 134328828Smm uid_t original_uid; 135328828Smm uid_t try_to_change_uid; 136228753Smm 137228753Smm assertUmask(UMASK); 138228753Smm 139228753Smm /* 140228753Smm * Set ownership of the current directory to the group of this 141228753Smm * process. Otherwise, the SGID tests below fail if the 142228753Smm * /tmp directory is owned by a group to which we don't belong 143228753Smm * and we're on a system where group ownership is inherited. 144228753Smm * (Because we're not allowed to SGID files with defaultgid().) 145228753Smm */ 146228753Smm assertEqualInt(0, chown(".", getuid(), getgid())); 147228753Smm 148228753Smm /* Create an archive_write_disk object. */ 149228753Smm assert((a = archive_write_disk_new()) != NULL); 150228753Smm 151228753Smm /* Write a regular file to it. */ 152228753Smm assert((ae = archive_entry_new()) != NULL); 153228753Smm archive_entry_copy_pathname(ae, "file_0755"); 154228753Smm archive_entry_set_mode(ae, S_IFREG | 0777); 155302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 156302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 157228753Smm archive_entry_free(ae); 158228753Smm 159228753Smm /* Write a regular file, then write over it. */ 160228753Smm /* For files, the perms should get updated. */ 161228753Smm assert((ae = archive_entry_new()) != NULL); 162228753Smm archive_entry_copy_pathname(ae, "file_overwrite_0144"); 163228753Smm archive_entry_set_mode(ae, S_IFREG | 0777); 164302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 165228753Smm archive_entry_free(ae); 166302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 167228753Smm /* Check that file was created with different perms. */ 168302001Smm assertEqualInt(0, stat("file_overwrite_0144", &st)); 169228753Smm failure("file_overwrite_0144: st.st_mode=%o", st.st_mode); 170228753Smm assert((st.st_mode & 07777) != 0144); 171228753Smm /* Overwrite, this should change the perms. */ 172228753Smm assert((ae = archive_entry_new()) != NULL); 173228753Smm archive_entry_copy_pathname(ae, "file_overwrite_0144"); 174228753Smm archive_entry_set_mode(ae, S_IFREG | 0144); 175302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 176228753Smm archive_entry_free(ae); 177302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 178228753Smm 179228753Smm /* Write a regular dir. */ 180228753Smm assert((ae = archive_entry_new()) != NULL); 181228753Smm archive_entry_copy_pathname(ae, "dir_0514"); 182228753Smm archive_entry_set_mode(ae, S_IFDIR | 0514); 183302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 184228753Smm archive_entry_free(ae); 185302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 186228753Smm 187228753Smm /* Overwrite an existing dir. */ 188228753Smm /* For dir, the first perms should get left. */ 189228753Smm assertMakeDir("dir_overwrite_0744", 0744); 190228753Smm /* Check original perms. */ 191302001Smm assertEqualInt(0, stat("dir_overwrite_0744", &st)); 192228753Smm failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); 193302001Smm assertEqualInt(st.st_mode & 0777, 0744); 194228753Smm /* Overwrite shouldn't edit perms. */ 195228753Smm assert((ae = archive_entry_new()) != NULL); 196228753Smm archive_entry_copy_pathname(ae, "dir_overwrite_0744"); 197228753Smm archive_entry_set_mode(ae, S_IFDIR | 0777); 198302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 199228753Smm archive_entry_free(ae); 200302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 201228753Smm /* Make sure they're unchanged. */ 202302001Smm assertEqualInt(0, stat("dir_overwrite_0744", &st)); 203228753Smm failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); 204302001Smm assertEqualInt(st.st_mode & 0777, 0744); 205228753Smm 206328828Smm /* For dir, the owner should get left when not overwritting. */ 207328828Smm assertMakeDir("dir_owner", 0744); 208328828Smm 209328828Smm if (getuid() == 0) { 210328828Smm original_uid = getuid() + 1; 211328828Smm try_to_change_uid = getuid(); 212328828Smm assertEqualInt(0, chown("dir_owner", original_uid, getgid())); 213328828Smm } else { 214328828Smm original_uid = getuid(); 215328828Smm try_to_change_uid = getuid() + 1; 216328828Smm } 217328828Smm 218328828Smm /* Check original owner. */ 219328828Smm assertEqualInt(0, stat("dir_owner", &st)); 220328828Smm failure("dir_owner: st.st_uid=%d", st.st_uid); 221328828Smm assertEqualInt(st.st_uid, original_uid); 222328828Smm /* Shouldn't try to edit the owner when no overwrite option is set. */ 223328828Smm assert((ae = archive_entry_new()) != NULL); 224328828Smm archive_entry_copy_pathname(ae, "dir_owner"); 225328828Smm archive_entry_set_mode(ae, S_IFDIR | 0744); 226328828Smm archive_entry_set_uid(ae, try_to_change_uid); 227328828Smm archive_write_disk_set_options(a, 228328828Smm ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_NO_OVERWRITE); 229328828Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 230328828Smm archive_entry_free(ae); 231328828Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 232328828Smm /* Make sure they're unchanged. */ 233328828Smm assertEqualInt(0, stat("dir_owner", &st)); 234328828Smm failure("dir_owner: st.st_uid=%d", st.st_uid); 235328828Smm assertEqualInt(st.st_uid, original_uid); 236328828Smm 237228753Smm /* Write a regular file with SUID bit, but don't use _EXTRACT_PERM. */ 238228753Smm assert((ae = archive_entry_new()) != NULL); 239228753Smm archive_entry_copy_pathname(ae, "file_no_suid"); 240228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0777); 241228753Smm archive_write_disk_set_options(a, 0); 242302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 243302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 244228753Smm 245228753Smm /* Write a regular file with ARCHIVE_EXTRACT_PERM. */ 246228753Smm assert(archive_entry_clear(ae) != NULL); 247228753Smm archive_entry_copy_pathname(ae, "file_0777"); 248228753Smm archive_entry_set_mode(ae, S_IFREG | 0777); 249228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); 250302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 251302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 252228753Smm 253228753Smm /* Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit */ 254228753Smm assert(archive_entry_clear(ae) != NULL); 255228753Smm archive_entry_copy_pathname(ae, "file_4742"); 256228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742); 257228753Smm archive_entry_set_uid(ae, getuid()); 258228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); 259302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 260302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 261228753Smm 262228753Smm /* 263228753Smm * Write a regular file with ARCHIVE_EXTRACT_PERM & SUID bit, 264228753Smm * but wrong uid. POSIX says you shouldn't restore SUID bit 265228753Smm * unless the UID could be restored. 266228753Smm */ 267228753Smm assert(archive_entry_clear(ae) != NULL); 268228753Smm archive_entry_copy_pathname(ae, "file_bad_suid"); 269228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742); 270228753Smm archive_entry_set_uid(ae, getuid() + 1); 271228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); 272228753Smm assertA(0 == archive_write_header(a, ae)); 273228753Smm /* 274228753Smm * Because we didn't ask for owner, the failure to 275228753Smm * restore SUID shouldn't return a failure. 276228753Smm * We check below to make sure SUID really wasn't set. 277228753Smm * See more detailed comments below. 278228753Smm */ 279228753Smm failure("Opportunistic SUID failure shouldn't return error."); 280228753Smm assertEqualInt(0, archive_write_finish_entry(a)); 281228753Smm 282228753Smm if (getuid() != 0) { 283228753Smm assert(archive_entry_clear(ae) != NULL); 284228753Smm archive_entry_copy_pathname(ae, "file_bad_suid2"); 285228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISUID | 0742); 286228753Smm archive_entry_set_uid(ae, getuid() + 1); 287228753Smm archive_write_disk_set_options(a, 288228753Smm ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER); 289228753Smm assertA(0 == archive_write_header(a, ae)); 290228753Smm /* Owner change should fail here. */ 291228753Smm failure("Non-opportunistic SUID failure should return error."); 292228753Smm assertEqualInt(ARCHIVE_WARN, archive_write_finish_entry(a)); 293228753Smm } 294228753Smm 295228753Smm /* Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit */ 296228753Smm assert(archive_entry_clear(ae) != NULL); 297228753Smm archive_entry_copy_pathname(ae, "file_perm_sgid"); 298228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); 299228753Smm archive_entry_set_gid(ae, defaultgid()); 300228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); 301302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 302228753Smm failure("Setting SGID bit should succeed here."); 303228753Smm assertEqualIntA(a, 0, archive_write_finish_entry(a)); 304228753Smm 305228753Smm if (altgid() == -1) { 306228753Smm /* 307228753Smm * Current user must belong to at least two groups or 308228753Smm * else we can't test setting the GID to another group. 309228753Smm */ 310228753Smm skipping("Current user can't test gid restore: must belong to more than one group."); 311228753Smm } else { 312228753Smm /* 313228753Smm * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit 314228753Smm * but without ARCHIVE_EXTRACT_OWNER. 315228753Smm */ 316228753Smm /* 317228753Smm * This is a weird case: The user has asked for permissions to 318228753Smm * be restored but not asked for ownership to be restored. As 319228753Smm * a result, the default file creation will create a file with 320228753Smm * the wrong group. There are several possible behaviors for 321228753Smm * libarchive in this scenario: 322228753Smm * = Set the SGID bit. It is wrong and a security hole to 323228753Smm * set SGID with the wrong group. Even POSIX thinks so. 324228753Smm * = Implicitly set the group. I don't like this. 325228753Smm * = drop the SGID bit and warn (the old libarchive behavior) 326228753Smm * = drop the SGID bit and don't warn (the current libarchive 327228753Smm * behavior). 328228753Smm * The current behavior sees SGID/SUID restore when you 329228753Smm * don't ask for owner restore as an "opportunistic" 330228753Smm * action. That is, libarchive should do it if it can, 331228753Smm * but if it can't, it's not an error. 332228753Smm */ 333228753Smm assert(archive_entry_clear(ae) != NULL); 334228753Smm archive_entry_copy_pathname(ae, "file_alt_sgid"); 335228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); 336228753Smm archive_entry_set_uid(ae, getuid()); 337228753Smm archive_entry_set_gid(ae, altgid()); 338228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); 339302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 340228753Smm 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."); 341228753Smm assertEqualIntA(a, 0, archive_write_finish_entry(a)); 342228753Smm 343228753Smm /* 344228753Smm * As above, but add _EXTRACT_OWNER to verify that it 345228753Smm * does succeed. 346228753Smm */ 347228753Smm assert(archive_entry_clear(ae) != NULL); 348228753Smm archive_entry_copy_pathname(ae, "file_alt_sgid_owner"); 349228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); 350228753Smm archive_entry_set_uid(ae, getuid()); 351228753Smm archive_entry_set_gid(ae, altgid()); 352228753Smm archive_write_disk_set_options(a, 353228753Smm ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER); 354302001Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 355228753Smm failure("Setting SGID bit should succeed here."); 356228753Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a)); 357228753Smm } 358228753Smm 359228753Smm /* 360228753Smm * Write a regular file with ARCHIVE_EXTRACT_PERM & SGID bit, 361228753Smm * but wrong GID. POSIX says you shouldn't restore SGID bit 362228753Smm * unless the GID could be restored. 363228753Smm */ 364228753Smm if (invalidgid() == -1) { 365228753Smm /* This test always fails for root. */ 366228753Smm printf("Running as root: Can't test SGID failures.\n"); 367228753Smm } else { 368228753Smm assert(archive_entry_clear(ae) != NULL); 369228753Smm archive_entry_copy_pathname(ae, "file_bad_sgid"); 370228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); 371228753Smm archive_entry_set_gid(ae, invalidgid()); 372228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_PERM); 373228753Smm assertA(0 == archive_write_header(a, ae)); 374228753Smm failure("This SGID restore should fail without an error."); 375228753Smm assertEqualIntA(a, 0, archive_write_finish_entry(a)); 376228753Smm 377228753Smm assert(archive_entry_clear(ae) != NULL); 378228753Smm archive_entry_copy_pathname(ae, "file_bad_sgid2"); 379228753Smm archive_entry_set_mode(ae, S_IFREG | S_ISGID | 0742); 380228753Smm archive_entry_set_gid(ae, invalidgid()); 381228753Smm archive_write_disk_set_options(a, 382228753Smm ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_OWNER); 383228753Smm assertA(0 == archive_write_header(a, ae)); 384228753Smm failure("This SGID restore should fail with an error."); 385228753Smm assertEqualIntA(a, ARCHIVE_WARN, archive_write_finish_entry(a)); 386228753Smm } 387228753Smm 388228753Smm /* Set ownership should fail if we're not root. */ 389228753Smm if (getuid() == 0) { 390228753Smm printf("Running as root: Can't test setuid failures.\n"); 391228753Smm } else { 392228753Smm assert(archive_entry_clear(ae) != NULL); 393228753Smm archive_entry_copy_pathname(ae, "file_bad_owner"); 394228753Smm archive_entry_set_mode(ae, S_IFREG | 0744); 395228753Smm archive_entry_set_uid(ae, getuid() + 1); 396228753Smm archive_write_disk_set_options(a, ARCHIVE_EXTRACT_OWNER); 397228753Smm assertA(0 == archive_write_header(a, ae)); 398228753Smm assertEqualIntA(a,ARCHIVE_WARN,archive_write_finish_entry(a)); 399228753Smm } 400228753Smm 401232153Smm assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 402228753Smm archive_entry_free(ae); 403228753Smm 404228753Smm /* Test the entries on disk. */ 405302001Smm assertEqualInt(0, stat("file_0755", &st)); 406228753Smm failure("file_0755: st.st_mode=%o", st.st_mode); 407302001Smm assertEqualInt(st.st_mode & 07777, 0755); 408228753Smm 409302001Smm assertEqualInt(0, stat("file_overwrite_0144", &st)); 410228753Smm failure("file_overwrite_0144: st.st_mode=%o", st.st_mode); 411302001Smm assertEqualInt(st.st_mode & 07777, 0144); 412228753Smm 413302001Smm assertEqualInt(0, stat("dir_0514", &st)); 414228753Smm failure("dir_0514: st.st_mode=%o", st.st_mode); 415302001Smm assertEqualInt(st.st_mode & 07777, 0514); 416228753Smm 417302001Smm assertEqualInt(0, stat("dir_overwrite_0744", &st)); 418228753Smm failure("dir_overwrite_0744: st.st_mode=%o", st.st_mode); 419302001Smm assertEqualInt(st.st_mode & 0777, 0744); 420228753Smm 421302001Smm assertEqualInt(0, stat("file_no_suid", &st)); 422228753Smm failure("file_0755: st.st_mode=%o", st.st_mode); 423302001Smm assertEqualInt(st.st_mode & 07777, 0755); 424228753Smm 425302001Smm assertEqualInt(0, stat("file_0777", &st)); 426228753Smm failure("file_0777: st.st_mode=%o", st.st_mode); 427302001Smm assertEqualInt(st.st_mode & 07777, 0777); 428228753Smm 429228753Smm /* SUID bit should get set here. */ 430302001Smm assertEqualInt(0, stat("file_4742", &st)); 431228753Smm failure("file_4742: st.st_mode=%o", st.st_mode); 432302001Smm assertEqualInt(st.st_mode & 07777, S_ISUID | 0742); 433228753Smm 434228753Smm /* SUID bit should NOT have been set here. */ 435302001Smm assertEqualInt(0, stat("file_bad_suid", &st)); 436228753Smm failure("file_bad_suid: st.st_mode=%o", st.st_mode); 437302001Smm assertEqualInt(st.st_mode & 07777, 0742); 438228753Smm 439228753Smm /* Some things don't fail if you're root, so suppress this. */ 440228753Smm if (getuid() != 0) { 441228753Smm /* SUID bit should NOT have been set here. */ 442302001Smm assertEqualInt(0, stat("file_bad_suid2", &st)); 443228753Smm failure("file_bad_suid2: st.st_mode=%o", st.st_mode); 444302001Smm assertEqualInt(st.st_mode & 07777, 0742); 445228753Smm } 446228753Smm 447228753Smm /* SGID should be set here. */ 448302001Smm assertEqualInt(0, stat("file_perm_sgid", &st)); 449228753Smm failure("file_perm_sgid: st.st_mode=%o", st.st_mode); 450302001Smm assertEqualInt(st.st_mode & 07777, S_ISGID | 0742); 451228753Smm 452228753Smm if (altgid() != -1) { 453228753Smm /* SGID should not be set here. */ 454302001Smm assertEqualInt(0, stat("file_alt_sgid", &st)); 455228753Smm failure("file_alt_sgid: st.st_mode=%o", st.st_mode); 456302001Smm assertEqualInt(st.st_mode & 07777, 0742); 457228753Smm 458228753Smm /* SGID should be set here. */ 459302001Smm assertEqualInt(0, stat("file_alt_sgid_owner", &st)); 460228753Smm failure("file_alt_sgid: st.st_mode=%o", st.st_mode); 461302001Smm assertEqualInt(st.st_mode & 07777, S_ISGID | 0742); 462228753Smm } 463228753Smm 464228753Smm if (invalidgid() != -1) { 465228753Smm /* SGID should NOT be set here. */ 466302001Smm assertEqualInt(0, stat("file_bad_sgid", &st)); 467228753Smm failure("file_bad_sgid: st.st_mode=%o", st.st_mode); 468302001Smm assertEqualInt(st.st_mode & 07777, 0742); 469228753Smm /* SGID should NOT be set here. */ 470302001Smm assertEqualInt(0, stat("file_bad_sgid2", &st)); 471228753Smm failure("file_bad_sgid2: st.st_mode=%o", st.st_mode); 472302001Smm assertEqualInt(st.st_mode & 07777, 0742); 473228753Smm } 474228753Smm 475228753Smm if (getuid() != 0) { 476302001Smm assertEqualInt(0, stat("file_bad_owner", &st)); 477228753Smm failure("file_bad_owner: st.st_mode=%o", st.st_mode); 478302001Smm assertEqualInt(st.st_mode & 07777, 0744); 479228753Smm failure("file_bad_owner: st.st_uid=%d getuid()=%d", 480228753Smm st.st_uid, getuid()); 481228753Smm /* The entry had getuid()+1, but because we're 482228753Smm * not root, we should not have been able to set that. */ 483302001Smm assertEqualInt(st.st_uid, getuid()); 484228753Smm } 485228753Smm#endif 486228753Smm} 487