ATF_TC_BODY(is_root, tc) { if (geteuid() == 0) ATF_REQUIRE(atf_user_is_root()); else ATF_REQUIRE(!atf_user_is_root()); }
/* * An implementation of access(2) but using the effective user value * instead of the real one. Also avoids false positives for root when * asking for execute permissions, which appear in SunOS. */ atf_error_t atf_fs_eaccess(const atf_fs_path_t *p, int mode) { atf_error_t err; struct stat st; bool ok; PRE(mode & atf_fs_access_f || mode & atf_fs_access_r || mode & atf_fs_access_w || mode & atf_fs_access_x); if (lstat(atf_fs_path_cstring(p), &st) == -1) { err = atf_libc_error(errno, "Cannot get information from file %s", atf_fs_path_cstring(p)); goto out; } err = atf_no_error(); /* Early return if we are only checking for existence and the file * exists (stat call returned). */ if (mode & atf_fs_access_f) goto out; ok = false; if (atf_user_is_root()) { if (!ok && !(mode & atf_fs_access_x)) { /* Allow root to read/write any file. */ ok = true; } if (!ok && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) { /* Allow root to execute the file if any of its execution bits * are set. */ ok = true; } } else { if (!ok && (atf_user_euid() == st.st_uid)) { ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRUSR)) || ((mode & atf_fs_access_w) && (st.st_mode & S_IWUSR)) || ((mode & atf_fs_access_x) && (st.st_mode & S_IXUSR)); } if (!ok && atf_user_is_member_of_group(st.st_gid)) { ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IRGRP)) || ((mode & atf_fs_access_w) && (st.st_mode & S_IWGRP)) || ((mode & atf_fs_access_x) && (st.st_mode & S_IXGRP)); } if (!ok && ((atf_user_euid() != st.st_uid) && !atf_user_is_member_of_group(st.st_gid))) { ok = ((mode & atf_fs_access_r) && (st.st_mode & S_IROTH)) || ((mode & atf_fs_access_w) && (st.st_mode & S_IWOTH)) || ((mode & atf_fs_access_x) && (st.st_mode & S_IXOTH)); } } if (!ok) err = atf_libc_error(EACCES, "Access check failed"); out: return err; }
ATF_TC_BODY(exists, tc) { atf_error_t err; atf_fs_path_t pdir, pfile; bool b; RE(atf_fs_path_init_fmt(&pdir, "dir")); RE(atf_fs_path_init_fmt(&pfile, "dir/file")); create_dir(atf_fs_path_cstring(&pdir), 0755); create_file(atf_fs_path_cstring(&pfile), 0644); printf("Checking existence of a directory\n"); RE(atf_fs_exists(&pdir, &b)); ATF_REQUIRE(b); printf("Checking existence of a file\n"); RE(atf_fs_exists(&pfile, &b)); ATF_REQUIRE(b); /* XXX: This should probably be a separate test case to let the user * be aware that some tests were skipped because privileges were not * correct. */ if (!atf_user_is_root()) { printf("Checking existence of a file inside a directory without " "permissions\n"); ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0000) != -1); err = atf_fs_exists(&pfile, &b); ATF_REQUIRE(atf_is_error(err)); ATF_REQUIRE(atf_error_is(err, "libc")); ATF_REQUIRE(chmod(atf_fs_path_cstring(&pdir), 0755) != -1); atf_error_free(err); } printf("Checking existence of a non-existent file\n"); ATF_REQUIRE(unlink(atf_fs_path_cstring(&pfile)) != -1); RE(atf_fs_exists(&pfile, &b)); ATF_REQUIRE(!b); atf_fs_path_fini(&pfile); atf_fs_path_fini(&pdir); }
ATF_TC_BODY(rmdir_eperm, tc) { atf_fs_path_t p; atf_error_t err; RE(atf_fs_path_init_fmt(&p, "test-dir/foo")); ATF_REQUIRE(mkdir("test-dir", 0755) != -1); ATF_REQUIRE(mkdir("test-dir/foo", 0755) != -1); ATF_REQUIRE(chmod("test-dir", 0555) != -1); ATF_REQUIRE(exists(&p)); err = atf_fs_rmdir(&p); if (atf_user_is_root()) { ATF_REQUIRE(!atf_is_error(err)); } else { ATF_REQUIRE(atf_is_error(err)); ATF_REQUIRE(atf_error_is(err, "libc")); ATF_REQUIRE_EQ(atf_libc_error_code(err), EACCES); atf_error_free(err); } atf_fs_path_fini(&p); }
ATF_TC_BODY(eaccess, tc) { const int modes[] = { atf_fs_access_f, atf_fs_access_r, atf_fs_access_w, atf_fs_access_x, 0 }; const int *m; struct tests { mode_t fmode; int amode; int uerror; int rerror; } tests[] = { { 0000, atf_fs_access_r, EACCES, 0 }, { 0000, atf_fs_access_w, EACCES, 0 }, { 0000, atf_fs_access_x, EACCES, EACCES }, { 0001, atf_fs_access_r, EACCES, 0 }, { 0001, atf_fs_access_w, EACCES, 0 }, { 0001, atf_fs_access_x, EACCES, 0 }, { 0002, atf_fs_access_r, EACCES, 0 }, { 0002, atf_fs_access_w, EACCES, 0 }, { 0002, atf_fs_access_x, EACCES, EACCES }, { 0004, atf_fs_access_r, EACCES, 0 }, { 0004, atf_fs_access_w, EACCES, 0 }, { 0004, atf_fs_access_x, EACCES, EACCES }, { 0010, atf_fs_access_r, EACCES, 0 }, { 0010, atf_fs_access_w, EACCES, 0 }, { 0010, atf_fs_access_x, 0, 0 }, { 0020, atf_fs_access_r, EACCES, 0 }, { 0020, atf_fs_access_w, 0, 0 }, { 0020, atf_fs_access_x, EACCES, EACCES }, { 0040, atf_fs_access_r, 0, 0 }, { 0040, atf_fs_access_w, EACCES, 0 }, { 0040, atf_fs_access_x, EACCES, EACCES }, { 0100, atf_fs_access_r, EACCES, 0 }, { 0100, atf_fs_access_w, EACCES, 0 }, { 0100, atf_fs_access_x, 0, 0 }, { 0200, atf_fs_access_r, EACCES, 0 }, { 0200, atf_fs_access_w, 0, 0 }, { 0200, atf_fs_access_x, EACCES, EACCES }, { 0400, atf_fs_access_r, 0, 0 }, { 0400, atf_fs_access_w, EACCES, 0 }, { 0400, atf_fs_access_x, EACCES, EACCES }, { 0, 0, 0, 0 } }; struct tests *t; atf_fs_path_t p; atf_error_t err; RE(atf_fs_path_init_fmt(&p, "the-file")); printf("Non-existent file checks\n"); for (m = &modes[0]; *m != 0; m++) { err = atf_fs_eaccess(&p, *m); ATF_REQUIRE(atf_is_error(err)); ATF_REQUIRE(atf_error_is(err, "libc")); ATF_REQUIRE_EQ(atf_libc_error_code(err), ENOENT); atf_error_free(err); } create_file(atf_fs_path_cstring(&p), 0000); ATF_REQUIRE(chown(atf_fs_path_cstring(&p), geteuid(), getegid()) != -1); for (t = &tests[0]; t->amode != 0; t++) { const int experr = atf_user_is_root() ? t->rerror : t->uerror; printf("\n"); printf("File mode : %04o\n", (unsigned int)t->fmode); printf("Access mode : 0x%02x\n", t->amode); ATF_REQUIRE(chmod(atf_fs_path_cstring(&p), t->fmode) != -1); /* First, existence check. */ err = atf_fs_eaccess(&p, atf_fs_access_f); ATF_REQUIRE(!atf_is_error(err)); /* Now do the specific test case. */ printf("Expected error: %d\n", experr); err = atf_fs_eaccess(&p, t->amode); if (atf_is_error(err)) { if (atf_error_is(err, "libc")) printf("Error : %d\n", atf_libc_error_code(err)); else printf("Error : Non-libc error\n"); } else printf("Error : None\n"); if (experr == 0) { ATF_REQUIRE(!atf_is_error(err)); } else { ATF_REQUIRE(atf_is_error(err)); ATF_REQUIRE(atf_error_is(err, "libc")); ATF_REQUIRE_EQ(atf_libc_error_code(err), experr); atf_error_free(err); } } atf_fs_path_fini(&p); }