static int change_serial(ntfs_volume *vol, u64 sector, le64 serial_number, NTFS_BOOT_SECTOR *bs, NTFS_BOOT_SECTOR *oldbs) { int res; le64 mask; BOOL same; res = -1; if ((ntfs_pread(vol->dev, sector << vol->sector_size_bits, vol->sector_size, bs) == vol->sector_size)) { same = TRUE; if (!sector) /* save the real bootsector */ memcpy(oldbs, bs, vol->sector_size); else /* backup bootsector must be similar */ same = !memcmp(oldbs, bs, vol->sector_size); if (same) { if (opts.new_serial & 2) bs->volume_serial_number = serial_number; else { mask = const_cpu_to_le64(~0x0ffffffffULL); bs->volume_serial_number = (serial_number & mask) | (bs->volume_serial_number & ~mask); } if (opts.noaction || (ntfs_pwrite(vol->dev, sector << vol->sector_size_bits, vol->sector_size, bs) == vol->sector_size)) { res = 0; } } else { ntfs_log_info("* Warning : the backup boot sector" " does not match (leaving unchanged)\n"); res = 0; } } return (res); }
/** * init_secure_sds - * * NTFS 3.1 - System files security decriptors * =========================================== * Create the security descriptor entries in $SDS data stream like they * are in a partition, newly formatted with windows 2003 */ void init_secure_sds(char *sd_val) { SECURITY_DESCRIPTOR_HEADER *sds; SECURITY_DESCRIPTOR_RELATIVE *sd; ACL *acl; ACCESS_ALLOWED_ACE *ace; SID *sid; /* * security descriptor #1 */ //header sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val); sds->hash = const_cpu_to_le32(0xF80312F0); sds->security_id = const_cpu_to_le32(0x0100); sds->offset = const_cpu_to_le64(0x00); sds->length = const_cpu_to_le32(0x7C); //security descriptor relative sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds + sizeof(SECURITY_DESCRIPTOR_HEADER)); sd->revision = 0x01; sd->alignment = 0x00; sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; sd->owner = const_cpu_to_le32(0x48); sd->group = const_cpu_to_le32(0x58); sd->sacl = const_cpu_to_le32(0x00); sd->dacl = const_cpu_to_le32(0x14); //acl acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); acl->revision = 0x02; acl->alignment1 = 0x00; acl->size = const_cpu_to_le16(0x34); acl->ace_count = const_cpu_to_le16(0x02); acl->alignment2 = 0x00; //ace1 ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x14); ace->mask = const_cpu_to_le32(0x120089); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //ace2 ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x18); ace->mask = const_cpu_to_le32(0x120089); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //owner sid sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //group sid sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); /* * security descriptor #2 */ //header sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80); sds->hash = const_cpu_to_le32(0xB32451); sds->security_id = const_cpu_to_le32(0x0101); sds->offset = const_cpu_to_le64(0x80); sds->length = const_cpu_to_le32(0x7C); //security descriptor relative sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds + sizeof(SECURITY_DESCRIPTOR_HEADER)); sd->revision = 0x01; sd->alignment = 0x00; sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; sd->owner = const_cpu_to_le32(0x48); sd->group = const_cpu_to_le32(0x58); sd->sacl = const_cpu_to_le32(0x00); sd->dacl = const_cpu_to_le32(0x14); //acl acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); acl->revision = 0x02; acl->alignment1 = 0x00; acl->size = const_cpu_to_le16(0x34); acl->ace_count = const_cpu_to_le16(0x02); acl->alignment2 = 0x00; //ace1 ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x14); ace->mask = const_cpu_to_le32(0x12019F); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x01; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); //ace2 ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); ace->type = 0x00; ace->flags = 0x00; ace->size = const_cpu_to_le16(0x18); ace->mask = const_cpu_to_le32(0x12019F); ace->sid.revision = 0x01; ace->sid.sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ ace->sid.identifier_authority.value[0] = 0; ace->sid.identifier_authority.value[1] = 0; ace->sid.identifier_authority.value[2] = 0; ace->sid.identifier_authority.value[3] = 0; ace->sid.identifier_authority.value[4] = 0; ace->sid.identifier_authority.value[5] = 5; ace->sid.sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //owner sid sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); //group sid sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); sid->revision = 0x01; sid->sub_authority_count = 0x02; /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ sid->identifier_authority.value[0] = 0; sid->identifier_authority.value[1] = 0; sid->identifier_authority.value[2] = 0; sid->identifier_authority.value[3] = 0; sid->identifier_authority.value[4] = 0; sid->identifier_authority.value[5] = 5; sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); return; }
/** * ntfs_inode_sync_file_name - update FILE_NAME attributes * @ni: ntfs inode to update FILE_NAME attributes * * Update all FILE_NAME attributes for inode @ni in the index. * * Return 0 on success or -1 on error with errno set to the error code. */ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni) { ntfs_attr_search_ctx *ctx = NULL; ntfs_index_context *ictx; ntfs_inode *index_ni; FILE_NAME_ATTR *fn; FILE_NAME_ATTR *fnx; REPARSE_POINT *rpp; le32 reparse_tag; int err = 0; ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no); ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!ctx) { err = errno; goto err_out; } /* Collect the reparse tag, if any */ reparse_tag = cpu_to_le32(0); if (ni->flags & FILE_ATTR_REPARSE_POINT) { if (!ntfs_attr_lookup(AT_REPARSE_POINT, NULL, 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { rpp = (REPARSE_POINT*)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); reparse_tag = rpp->reparse_tag; } ntfs_attr_reinit_search_ctx(ctx); } /* Walk through all FILE_NAME attributes and update them. */ while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) { fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); if (MREF_LE(fn->parent_directory) == ni->mft_no) { /* * WARNING: We cheat here and obtain 2 attribute * search contexts for one inode (first we obtained * above, second will be obtained inside * ntfs_index_lookup), it's acceptable for library, * but will deadlock in the kernel. */ index_ni = ni; } else if (dir_ni) index_ni = dir_ni; else index_ni = ntfs_inode_open(ni->vol, le64_to_cpu(fn->parent_directory)); if (!index_ni) { if (!err) err = errno; ntfs_log_perror("Failed to open inode %lld with index", (long long)le64_to_cpu(fn->parent_directory)); continue; } ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4); if (!ictx) { if (!err) err = errno; ntfs_log_perror("Failed to get index ctx, inode %lld", (long long)index_ni->mft_no); if ((ni != index_ni) && !dir_ni && ntfs_inode_close(index_ni) && !err) err = errno; continue; } if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) { if (!err) { if (errno == ENOENT) err = EIO; else err = errno; } ntfs_log_perror("Index lookup failed, inode %lld", (long long)index_ni->mft_no); ntfs_index_ctx_put(ictx); if (ni != index_ni && ntfs_inode_close(index_ni) && !err) err = errno; continue; } /* Update flags and file size. */ fnx = (FILE_NAME_ATTR *)ictx->data; fnx->file_attributes = (fnx->file_attributes & ~FILE_ATTR_VALID_FLAGS) | (ni->flags & FILE_ATTR_VALID_FLAGS); if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) fnx->data_size = fnx->allocated_size = const_cpu_to_le64(0); else { fnx->allocated_size = cpu_to_sle64(ni->allocated_size); fnx->data_size = cpu_to_sle64(ni->data_size); /* * The file name record has also to be fixed if some * attribute update implied the unnamed data to be * made non-resident */ fn->allocated_size = fnx->allocated_size; } /* update or clear the reparse tag in the index */ fnx->reparse_point_tag = reparse_tag; if (!test_nino_flag(ni, TimesSet)) { fnx->creation_time = ni->creation_time; fnx->last_data_change_time = ni->last_data_change_time; fnx->last_mft_change_time = ni->last_mft_change_time; fnx->last_access_time = ni->last_access_time; } else { fnx->creation_time = fn->creation_time; fnx->last_data_change_time = fn->last_data_change_time; fnx->last_mft_change_time = fn->last_mft_change_time; fnx->last_access_time = fn->last_access_time; } ntfs_index_entry_mark_dirty(ictx); ntfs_index_ctx_put(ictx); if ((ni != index_ni) && !dir_ni && ntfs_inode_close(index_ni) && !err) err = errno; } /* Check for real error occurred. */ if (errno != ENOENT) { err = errno; ntfs_log_perror("Attribute lookup failed, inode %lld", (long long)ni->mft_no); goto err_out; } ntfs_attr_put_search_ctx(ctx); if (err) { errno = err; return -1; } return 0; err_out: if (ctx) ntfs_attr_put_search_ctx(ctx); errno = err; return -1; }