/** * ecryptfs_initialize_file * * Cause the file to be changed from a basic empty file to an ecryptfs * file with a header and first data page. * * Returns zero on success */ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; int rc = 0; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out; } crypt_stat->flags |= ECRYPTFS_NEW_FILE; ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); rc = ecryptfs_new_file_context(ecryptfs_dentry); if (rc) { ecryptfs_printk(KERN_ERR, "Error creating new file " "context; rc = [%d]\n", rc); goto out; } rc = ecryptfs_write_metadata(ecryptfs_dentry); if (rc) { printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); goto out; } rc = grow_file(ecryptfs_dentry); if (rc) printk(KERN_ERR "Error growing file; rc = [%d]\n", rc); out: return rc; }
int exfat_truncate(struct exfat* ef, struct exfat_node* node, uint64_t size) { uint32_t c1 = bytes2clusters(ef, node->size); uint32_t c2 = bytes2clusters(ef, size); int rc = 0; if (node->references == 0 && node->parent) exfat_bug("no references, node changes can be lost"); if (node->size == size) return 0; if (c1 < c2) rc = grow_file(ef, node, c1, c2 - c1); else if (c1 > c2) rc = shrink_file(ef, node, c1, c1 - c2); if (rc != 0) return rc; rc = erase_range(ef, node, node->size, size); if (rc != 0) return rc; exfat_update_mtime(node); node->size = size; node->flags |= EXFAT_ATTRIB_DIRTY; return 0; }
/* check if the current directory allows exec mappings */ static int check_current_dir_for_exec(void) { int fd; char tmpfn[] = "anonmap.XXXXXX"; void *ret = MAP_FAILED; fd = mkstemps( tmpfn, 0 ); if (fd == -1) return 0; if (grow_file( fd, 1 )) { ret = mmap( NULL, get_page_size(), PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0 ); if (ret != MAP_FAILED) munmap( ret, get_page_size() ); } close( fd ); unlink( tmpfn ); return (ret != MAP_FAILED); }
/* create a temp file for anonymous mappings */ static int create_temp_file( file_pos_t size ) { char tmpfn[16]; int fd; sprintf( tmpfn, "anonmap.XXXXXX" ); /* create it in the server directory */ fd = mkstemps( tmpfn, 0 ); if (fd != -1) { if (!grow_file( fd, size )) { close( fd ); fd = -1; } unlink( tmpfn ); } else file_set_error(); return fd; }
/** * ecryptfs_initialize_file * * Cause the file to be changed from a basic empty file to an ecryptfs * file with a header and first data page. * * Returns zero on success */ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; int rc = 0; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out; } crypt_stat->flags |= ECRYPTFS_NEW_FILE; ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); rc = ecryptfs_new_file_context(ecryptfs_dentry); if (rc) { ecryptfs_printk(KERN_ERR, "Error creating new file " "context; rc = [%d]\n", rc); goto out; } if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) { rc = ecryptfs_init_persistent_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " "the persistent file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out; } } rc = ecryptfs_write_metadata(ecryptfs_dentry); if (rc) { printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); goto out; } rc = grow_file(ecryptfs_dentry); if (rc) printk(KERN_ERR "Error growing file; rc = [%d]\n", rc); out: return rc; }
/* create a temp file for anonymous mappings */ static int create_temp_file( file_pos_t size ) { static int temp_dir_fd = -1; char tmpfn[] = "anonmap.XXXXXX"; int fd; if (temp_dir_fd == -1) { temp_dir_fd = server_dir_fd; if (!check_current_dir_for_exec()) { /* the server dir is noexec, try the config dir instead */ fchdir( config_dir_fd ); if (check_current_dir_for_exec()) temp_dir_fd = config_dir_fd; else /* neither works, fall back to server dir */ fchdir( server_dir_fd ); } } else if (temp_dir_fd != server_dir_fd) fchdir( temp_dir_fd ); fd = mkstemps( tmpfn, 0 ); if (fd != -1) { if (!grow_file( fd, size )) { close( fd ); fd = -1; } unlink( tmpfn ); } else file_set_error(); if (temp_dir_fd != server_dir_fd) fchdir( server_dir_fd ); return fd; }
/** * ecryptfs_initialize_file * * Cause the file to be changed from a basic empty file to an ecryptfs * file with a header and first data page. * * Returns zero on success */ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) { struct ecryptfs_crypt_stat *crypt_stat = &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat; int rc = 0; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); goto out; } crypt_stat->flags |= ECRYPTFS_NEW_FILE; ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n"); rc = ecryptfs_new_file_context(ecryptfs_dentry); if (rc) { ecryptfs_printk(KERN_ERR, "Error creating new file " "context; rc = [%d]\n", rc); goto out; } if (!ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->lower_file) { rc = ecryptfs_init_persistent_file(ecryptfs_dentry); if (rc) { printk(KERN_ERR "%s: Error attempting to initialize " "the persistent file for the dentry with name " "[%s]; rc = [%d]\n", __func__, ecryptfs_dentry->d_name.name, rc); goto out; } } /* [email protected] encryption filter */ #ifdef WTL_ENCRYPTION_FILTER /* fzhang, TODO, should not change flags for existing encrypted files even through their ext match filter rule */ if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) { struct dentry *fp_dentry = ecryptfs_inode_to_private(ecryptfs_dentry->d_inode) ->lower_file->f_dentry; struct ecryptfs_mount_crypt_stat *mount_crypt_stat = &ecryptfs_superblock_to_private( ecryptfs_dentry->d_sb)->mount_crypt_stat; char filename[256]; strcpy(filename, fp_dentry->d_name.name); if ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_NEW_PASSTHROUGH) || ((mount_crypt_stat->flags & ECRYPTFS_ENABLE_FILTERING) && (is_file_name_match(mount_crypt_stat, fp_dentry) || is_file_ext_match(mount_crypt_stat, filename)))) { /*printk(KERN_ERR "fzhang %s will not be encrypted.\n", fp_dentry->d_iname); */ crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED); } else { rc = ecryptfs_write_metadata(ecryptfs_dentry); if (rc) { printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); goto out; } rc = grow_file(ecryptfs_dentry); if (rc) printk(KERN_ERR "Error growing file; rc = [%d]\n", rc); } } #else rc = ecryptfs_write_metadata(ecryptfs_dentry); if (rc) { printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc); goto out; } rc = grow_file(ecryptfs_dentry); if (rc) printk(KERN_ERR "Error growing file; rc = [%d]\n", rc); #endif out: return rc; }
static struct object *create_mapping( struct object *root, const struct unicode_str *name, unsigned int attr, mem_size_t size, unsigned int flags, obj_handle_t handle, unsigned int file_access, const struct security_descriptor *sd ) { struct mapping *mapping; struct file *file; struct fd *fd; int unix_fd; struct stat st; if (!page_mask) page_mask = sysconf( _SC_PAGESIZE ) - 1; if (!(mapping = create_named_object( root, &mapping_ops, name, attr, sd ))) return NULL; if (get_error() == STATUS_OBJECT_NAME_EXISTS) return &mapping->obj; /* Nothing else to do */ mapping->size = size; mapping->fd = NULL; mapping->shared = NULL; mapping->committed = NULL; if (!(mapping->flags = get_mapping_flags( handle, flags ))) goto error; if (handle) { const unsigned int sharing = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; unsigned int mapping_access = FILE_MAPPING_ACCESS; if (!(file = get_file_obj( current->process, handle, file_access ))) goto error; fd = get_obj_fd( (struct object *)file ); /* file sharing rules for mappings are different so we use magic the access rights */ if (flags & SEC_IMAGE) mapping_access |= FILE_MAPPING_IMAGE; else if (file_access & FILE_WRITE_DATA) mapping_access |= FILE_MAPPING_WRITE; if (!(mapping->fd = get_fd_object_for_mapping( fd, mapping_access, sharing ))) { mapping->fd = dup_fd_object( fd, mapping_access, sharing, FILE_SYNCHRONOUS_IO_NONALERT ); if (mapping->fd) set_fd_user( mapping->fd, &mapping_fd_ops, NULL ); } release_object( file ); release_object( fd ); if (!mapping->fd) goto error; if ((unix_fd = get_unix_fd( mapping->fd )) == -1) goto error; if (fstat( unix_fd, &st ) == -1) { file_set_error(); goto error; } if (flags & SEC_IMAGE) { unsigned int err = get_image_params( mapping, st.st_size, unix_fd ); if (!err) return &mapping->obj; set_error( err ); goto error; } if (!mapping->size) { if (!(mapping->size = st.st_size)) { set_error( STATUS_MAPPED_FILE_SIZE_ZERO ); goto error; } } else if (st.st_size < mapping->size) { if (!(file_access & FILE_WRITE_DATA)) { set_error( STATUS_SECTION_TOO_BIG ); goto error; } if (!grow_file( unix_fd, mapping->size )) goto error; } } else /* Anonymous mapping (no associated file) */ { if (!mapping->size) { set_error( STATUS_INVALID_PARAMETER ); goto error; } if ((flags & SEC_RESERVE) && !(mapping->committed = create_ranges())) goto error; mapping->size = (mapping->size + page_mask) & ~((mem_size_t)page_mask); if ((unix_fd = create_temp_file( mapping->size )) == -1) goto error; if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error; allow_fd_caching( mapping->fd ); } return &mapping->obj; error: release_object( mapping ); return NULL; }
static struct object *create_mapping( struct directory *root, const struct unicode_str *name, unsigned int attr, file_pos_t size, int protect, obj_handle_t handle ) { struct mapping *mapping; int access = 0; if (!page_mask) init_page_size(); if (!(mapping = create_named_object_dir( root, name, attr, &mapping_ops ))) return NULL; if (get_error() == STATUS_OBJECT_NAME_EXISTS) return &mapping->obj; /* Nothing else to do */ mapping->header_size = 0; mapping->base = NULL; mapping->shared_file = NULL; mapping->shared_size = 0; if (protect & VPROT_READ) access |= FILE_READ_DATA; if (protect & VPROT_WRITE) access |= FILE_WRITE_DATA; if (handle) { if (!(mapping->file = get_file_obj( current->process, handle, access ))) goto error; if (protect & VPROT_IMAGE) { if (!get_image_params( mapping )) goto error; return &mapping->obj; } if (!size) { if (!get_file_size( mapping->file, &size )) goto error; if (!size) { set_error( STATUS_MAPPED_FILE_SIZE_ZERO ); goto error; } } else { if (!grow_file( mapping->file, size )) goto error; } } else /* Anonymous mapping (no associated file) */ { if (!size || (protect & VPROT_IMAGE)) { set_error( STATUS_INVALID_PARAMETER ); mapping->file = NULL; goto error; } if (!(mapping->file = create_temp_file( access ))) goto error; if (!grow_file( mapping->file, size )) goto error; } mapping->size = (size + page_mask) & ~((file_pos_t)page_mask); mapping->protect = protect; return &mapping->obj; error: release_object( mapping ); return NULL; }
/* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) { unsigned int i, size, max_size, total_size; off_t shared_pos, read_pos, write_pos; char *buffer = NULL; int shared_fd; long toread; /* compute the total size of the shared mapping */ total_size = max_size = 0; for (i = 0; i < nb_sec; i++) { if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) && (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { size = get_section_filemap_size( &sec[i] ); if (size > max_size) max_size = size; total_size += get_section_map_size( &sec[i] ); } } if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */ if ((mapping->shared_file = get_shared_file( mapping ))) return 1; /* create a temp file for the mapping */ if (!(mapping->shared_file = create_temp_file( FILE_GENERIC_READ|FILE_GENERIC_WRITE ))) return 0; if (!grow_file( mapping->shared_file, total_size )) goto error; if ((shared_fd = get_file_unix_fd( mapping->shared_file )) == -1) goto error; if (!(buffer = malloc( max_size ))) goto error; /* copy the shared sections data into the temp file */ shared_pos = 0; for (i = 0; i < nb_sec; i++) { if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue; if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue; write_pos = shared_pos; shared_pos += get_section_map_size( &sec[i] ); read_pos = sec[i].PointerToRawData; size = get_section_filemap_size( &sec[i] ); if (!read_pos || !size) continue; toread = size; while (toread) { long res = pread( fd, buffer + sec[i].SizeOfRawData - toread, toread, read_pos ); if (res <= 0) goto error; toread -= res; read_pos += res; } if (pwrite( shared_fd, buffer, size, write_pos ) != size) goto error; } free( buffer ); return 1; error: release_object( mapping->shared_file ); mapping->shared_file = NULL; if (buffer) free( buffer ); return 0; }
/** * Grow file to given size (if it is smaller) and mmap it. * * @param size Number of objects of type T that should fit into this file * @param fd File descriptor * @throws Errors thrown by grow_file() or map() */ static T* grow_and_map(size_t size, int fd) { grow_file(size, fd); return map(size, fd, true); }