static void owner(const atf_tc_t *tc, const char *mp) { USES_OWNER; FSTEST_ENTER(); rump_pub_lwproc_rfork(RUMP_RFCFDG); if (rump_sys_setuid(1) == -1) atf_tc_fail_errno("setuid"); if (rump_sys_chown(".", 1, -1) != -1 || errno != EPERM) atf_tc_fail_errno("chown"); if (rump_sys_chmod(".", 0000) != -1 || errno != EPERM) atf_tc_fail_errno("chmod"); rump_pub_lwproc_releaselwp(); if (rump_sys_chown(".", 1, -1) == -1) atf_tc_fail_errno("chown"); rump_pub_lwproc_rfork(RUMP_RFCFDG); if (rump_sys_setuid(1) == -1) atf_tc_fail_errno("setuid"); if (rump_sys_chown(".", 1, -1) == -1) atf_tc_fail_errno("chown"); if (rump_sys_chmod(".", 0000) == -1) atf_tc_fail_errno("chmod"); rump_pub_lwproc_releaselwp(); FSTEST_EXIT(); }
static void attrs(const atf_tc_t *tc, const char *mp) { struct stat sb, sb2; struct timeval tv[2]; int fd; FSTEST_ENTER(); RL(fd = rump_sys_open(TESTFILE, O_RDWR | O_CREAT, 0755)); RL(rump_sys_close(fd)); RL(rump_sys_stat(TESTFILE, &sb)); if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) { RL(rump_sys_chown(TESTFILE, 1, 2)); sb.st_uid = 1; sb.st_gid = 2; RL(rump_sys_chmod(TESTFILE, 0123)); sb.st_mode = (sb.st_mode & ~ACCESSPERMS) | 0123; } tv[0].tv_sec = 1000000000; /* need something >1980 for msdosfs */ tv[0].tv_usec = 1; tv[1].tv_sec = 1000000002; /* need even seconds for msdosfs */ tv[1].tv_usec = 3; RL(rump_sys_utimes(TESTFILE, tv)); RL(rump_sys_utimes(TESTFILE, tv)); /* XXX: utimes & birthtime */ sb.st_atimespec.tv_sec = 1000000000; sb.st_atimespec.tv_nsec = 1000; sb.st_mtimespec.tv_sec = 1000000002; sb.st_mtimespec.tv_nsec = 3000; RL(rump_sys_stat(TESTFILE, &sb2)); #define CHECK(a) ATF_REQUIRE_EQ(sb.a, sb2.a) if (FSTYPE_ZFS(tc)) atf_tc_expect_fail("PR kern/47656: Test known to be broken"); if (!(FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc))) { CHECK(st_uid); CHECK(st_gid); CHECK(st_mode); } if (!FSTYPE_MSDOS(tc)) { /* msdosfs has only access date, not time */ CHECK(st_atimespec.tv_sec); } CHECK(st_mtimespec.tv_sec); if (!(FSTYPE_EXT2FS(tc) || FSTYPE_MSDOS(tc) || FSTYPE_SYSVBFS(tc) || FSTYPE_V7FS(tc))) { CHECK(st_atimespec.tv_nsec); CHECK(st_mtimespec.tv_nsec); } #undef CHECK FSTEST_EXIT(); }
int copy_file(FTSENT *entp, int dne) { static unsigned char buf[MAXBSIZE]; struct stat to_stat, *fs; int ch, checkch, rv, rcount, rval, tolnk, wcount, fdin, fdout; off_t off; fs = entp->fts_statp; tolnk = ((Rflag && !(Lflag || Hflag)) || Pflag); /* * If the file exists and we're interactive, verify with the user. * If the file DNE, set the mode to be the from file, minus setuid * bits, modified by the umask; arguably wrong, but it makes copying * executables work right and it's been that way forever. (The * other choice is 666 or'ed with the execute bits on the from file * modified by the umask.) */ if (!dne) { if (iflag) { (void)fprintf(stderr, "overwrite %s? ", to.p_path); checkch = ch = getchar(); while (ch != '\n' && ch != EOF) ch = getchar(); if (checkch != 'y' && checkch != 'Y') return (0); } rump_sys_unlink(to.p_path); } rv = rump_sys_open(to.p_path, fs->st_mode & ~(S_ISUID | S_ISGID)); if (rv == -1 && (fflag || tolnk)) { /* * attempt to remove existing destination file name and * create a new file */ rump_sys_unlink(to.p_path); rv = rump_sys_open(to.p_path, fs->st_mode & ~(S_ISUID | S_ISGID)); if (rv == -1) { warn("%s", to.p_path); return (1); } } fdout = rv; fdin = rump_sys_open(entp->fts_path, O_RDONLY); rval = 0; /* * There's no reason to do anything other than close the file * now if it's empty, so let's not bother. */ off = 0; if (fs->st_size > 0) { while ((rcount = rump_sys_read(fdin, buf, MAXBSIZE)) > 0) { wcount = rump_sys_write(fdout, buf, (size_t)rcount); if (rcount != wcount || wcount == -1) { warn("%s", to.p_path); rval = 1; break; } off += rcount; } if (rcount < 0) { warn("%s", entp->fts_path); rval = 1; } } if (rval == 1) return (1); if (pflag && setfile(fs, 0)) rval = 1; /* * If the source was setuid or setgid, lose the bits unless the * copy is owned by the same user and group. */ #define RETAINBITS \ (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) if (!pflag && dne && fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) { if (rump_sys_stat(to.p_path, &to_stat)) { warn("%s", to.p_path); rval = 1; } else if (fs->st_gid == to_stat.st_gid && rump_sys_chmod(to.p_path, fs->st_mode & RETAINBITS & ~myumask)) { warn("%s", to.p_path); rval = 1; } } /* set the mod/access times now after close of the fd */ if (pflag && set_utimes(to.p_path, fs)) { rval = 1; } return (rval); }