static void test_safe_lchown_unsafe_link(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_FILE; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR "/" TEST_FILE; // Not calling this function will call it right in the middle of the // safe_open() instead. //test_switch_symlink(); assert_int_equal(lchown(TEST_SUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); // Unsafe links should succeed, because we are operating on the *link*, not the target. assert_int_equal(safe_lchown(TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); }
static void test_safe_lchown_unsafe_link_to_directory(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; TEST_SYMLINK_COUNTDOWN = 1; TEST_SYMLINK_NAME = TEMP_DIR "/" TEST_LINK; TEST_SYMLINK_TARGET = TEMP_DIR "/" TEST_SUBDIR; test_switch_symlink(); assert_int_equal(lchown(TEST_SUBDIR "/" TEST_FILE, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); assert_int_equal(lchown(TEST_SUBDIR, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); assert_int_equal(safe_lchown(TEST_LINK "/" TEST_FILE, 100, 100), -1); assert_int_equal(errno, EACCES); assert_int_equal(lchown(TEST_SUBDIR "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(lchown(TEST_SUBDIR, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEST_LINK "/" TEST_FILE, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR "/" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); return_to_test_dir(); }
static void test_safe_lchown_file_extra_slashes(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, 100, 100), 0); assert_int_equal(stat("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, 0, 0), 0); assert_int_equal(stat("/" TEMP_DIR "////" TEST_SUBSUBDIR "//" TEST_FILE, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); }
static void test_safe_lchown_plain_directory(void) { if (getuid() != 0) { complain_missing_sudo(__FUNCTION__); return; } setup_tempfiles(); struct stat statbuf; assert_int_equal(lchown(TEST_SUBDIR, 100, 100), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 100); assert_int_equal(statbuf.st_gid, 100); assert_int_equal(safe_lchown(TEST_SUBDIR, 0, 0), 0); assert_int_equal(stat(TEST_SUBDIR, &statbuf), 0); assert_int_equal(statbuf.st_uid, 0); assert_int_equal(statbuf.st_gid, 0); return_to_test_dir(); }
void process_chunk(void) { yaffs_ObjectHeader oh; yaffs_PackedTags2 *pt; object *obj, *eq_obj; int out_file, remain, s; oh = *(yaffs_ObjectHeader *)chunk_data; pt = (yaffs_PackedTags2 *)spare_data; if (pt->t.sequenceNumber == 0xffffffff) /* empty object */ return; if (saved_chunk.objectId != 0 && /* saved chunk is not part of object */ saved_chunk.objectId != pt->t.objectId) { prt_err(0, 0, "Warning: Invalid header at chunk #%d, skipping...", saved_chunk.chunk_no); if (++warn_count >= MAX_WARN) prt_err(1, 0, "Giving up"); saved_chunk.objectId = 0; } if (pt->t.chunkId == 1) { /* save chunk #1 */ saved_chunk.objectId = pt->t.objectId; saved_chunk.chunk_no = chunk_no; memcpy(saved_chunk.data, chunk_data, chunk_size); memcpy(saved_chunk.data+chunk_size, spare_data, spare_size); return; } else if (pt->t.chunkId != 0) { /* not a new object */ prt_err(0, 0, "Warning: Invalid header at chunk #%d, skipping...", chunk_no); if (++warn_count >= MAX_WARN) prt_err(1, 0, "Giving up"); return; } obj = add_object(&oh, pt); /* listing */ if (opt_verbose) prt_node(obj->path_name, &oh); else if (opt_list) printf("%s\n", obj->path_name); if (opt_list) { if (oh.type == YAFFS_OBJECT_TYPE_FILE) { remain = oh.fileSize; /* skip over data chunks */ while(remain > 0) { if (!next_data_chunk()) prt_err(1, 0, "Broken image file"); remain -= pt->t.byteCount; } } return; } switch(oh.type) { case YAFFS_OBJECT_TYPE_FILE: remain = oh.fileSize; out_file = creat(obj->path_name, oh.yst_mode & STD_PERMS); if (out_file < 0) prt_err(1, errno, "Can't create file %s", obj->path_name); while(remain > 0) { if (!next_data_chunk()) prt_err(1, 0, "Broken image file"); s = (remain < pt->t.byteCount) ? remain : pt->t.byteCount; if (safe_write(out_file, chunk_data, s) < 0) prt_err(1, errno, "Can't write to %s", obj->path_name); remain -= s; } close(out_file); safe_lchown(obj->path_name, oh.yst_uid, oh.yst_gid); if ((oh.yst_mode & EXTRA_PERMS) != 0 && chmod(obj->path_name, oh.yst_mode) < 0) prt_err(0, errno, "Warning: Can't chmod %s", obj->path_name); break; case YAFFS_OBJECT_TYPE_SYMLINK: if (symlink(oh.alias, obj->path_name) < 0) prt_err(1, errno, "Can't create symlink %s", obj->path_name); safe_lchown(obj->path_name, oh.yst_uid, oh.yst_gid); break; case YAFFS_OBJECT_TYPE_DIRECTORY: if (pt->t.objectId != YAFFS_OBJECTID_ROOT && mkdir(obj->path_name, oh.yst_mode & STD_PERMS) < 0) prt_err(1, errno, "Can't create directory %s", obj->path_name); safe_lchown(obj->path_name, oh.yst_uid, oh.yst_gid); if ((pt->t.objectId == YAFFS_OBJECTID_ROOT || (oh.yst_mode & EXTRA_PERMS) != 0) && chmod(obj->path_name, oh.yst_mode) < 0) prt_err(0, errno, "Warning: Can't chmod %s", obj->path_name); break; case YAFFS_OBJECT_TYPE_HARDLINK: eq_obj = get_object(oh.equivalentObjectId); if (eq_obj == NULL) prt_err(1, 0, "Invalid equivalentObjectId %u in object %u (%s)", oh.equivalentObjectId, pt->t.objectId, oh.name); if (link(eq_obj->path_name, obj->path_name) < 0) prt_err(1, errno, "Can't create hardlink %s", obj->path_name); break; case YAFFS_OBJECT_TYPE_SPECIAL: if (mknod(obj->path_name, oh.yst_mode, oh.yst_rdev) < 0) { if (errno == EPERM || errno == EINVAL) prt_err(0, errno, "Warning: Can't create device %s", obj->path_name); else prt_err(1, errno, "Can't create device %s", obj->path_name); } else safe_lchown(obj->path_name, oh.yst_uid, oh.yst_gid); break; case YAFFS_OBJECT_TYPE_UNKNOWN: break; } /* set file date and time */ switch(oh.type) { case YAFFS_OBJECT_TYPE_FILE: case YAFFS_OBJECT_TYPE_SPECIAL: #ifdef HAS_LUTIMES case YAFFS_OBJECT_TYPE_SYMLINK: #endif set_utime(obj->path_name, oh.yst_atime, oh.yst_mtime); break; case YAFFS_OBJECT_TYPE_DIRECTORY: default: break; } }