1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <sys/stat.h> 18#include <string.h> 19#include <stdio.h> 20 21#ifdef HAVE_ANDROID_OS 22#include <linux/capability.h> 23#else 24#include <private/android_filesystem_capability.h> 25#endif 26 27#define XATTR_SELINUX_SUFFIX "selinux" 28#define XATTR_CAPS_SUFFIX "capability" 29 30#include "ext4_utils.h" 31#include "make_ext4fs.h" 32#include "allocate.h" 33#include "contents.h" 34#include "extent.h" 35#include "indirect.h" 36 37#ifdef USE_MINGW 38#define S_IFLNK 0 /* used by make_link, not needed under mingw */ 39#endif 40 41static struct block_allocation* saved_allocation_head = NULL; 42 43struct block_allocation* get_saved_allocation_chain() { 44 return saved_allocation_head; 45} 46 47static u32 dentry_size(u32 entries, struct dentry *dentries) 48{ 49 u32 len = 24; 50 unsigned int i; 51 unsigned int dentry_len; 52 53 for (i = 0; i < entries; i++) { 54 dentry_len = 8 + EXT4_ALIGN(strlen(dentries[i].filename), 4); 55 if (len % info.block_size + dentry_len > info.block_size) 56 len += info.block_size - (len % info.block_size); 57 len += dentry_len; 58 } 59 60 return len; 61} 62 63static struct ext4_dir_entry_2 *add_dentry(u8 *data, u32 *offset, 64 struct ext4_dir_entry_2 *prev, u32 inode, const char *name, 65 u8 file_type) 66{ 67 u8 name_len = strlen(name); 68 u16 rec_len = 8 + EXT4_ALIGN(name_len, 4); 69 struct ext4_dir_entry_2 *dentry; 70 71 u32 start_block = *offset / info.block_size; 72 u32 end_block = (*offset + rec_len - 1) / info.block_size; 73 if (start_block != end_block) { 74 /* Adding this dentry will cross a block boundary, so pad the previous 75 dentry to the block boundary */ 76 if (!prev) 77 critical_error("no prev"); 78 prev->rec_len += end_block * info.block_size - *offset; 79 *offset = end_block * info.block_size; 80 } 81 82 dentry = (struct ext4_dir_entry_2 *)(data + *offset); 83 dentry->inode = inode; 84 dentry->rec_len = rec_len; 85 dentry->name_len = name_len; 86 dentry->file_type = file_type; 87 memcpy(dentry->name, name, name_len); 88 89 *offset += rec_len; 90 return dentry; 91} 92 93/* Creates a directory structure for an array of directory entries, dentries, 94 and stores the location of the structure in an inode. The new inode's 95 .. link is set to dir_inode_num. Stores the location of the inode number 96 of each directory entry into dentries[i].inode, to be filled in later 97 when the inode for the entry is allocated. Returns the inode number of the 98 new directory */ 99u32 make_directory(u32 dir_inode_num, u32 entries, struct dentry *dentries, 100 u32 dirs) 101{ 102 struct ext4_inode *inode; 103 u32 blocks; 104 u32 len; 105 u32 offset = 0; 106 u32 inode_num; 107 u8 *data; 108 unsigned int i; 109 struct ext4_dir_entry_2 *dentry; 110 111 blocks = DIV_ROUND_UP(dentry_size(entries, dentries), info.block_size); 112 len = blocks * info.block_size; 113 114 if (dir_inode_num) { 115 inode_num = allocate_inode(info); 116 } else { 117 dir_inode_num = EXT4_ROOT_INO; 118 inode_num = EXT4_ROOT_INO; 119 } 120 121 if (inode_num == EXT4_ALLOCATE_FAILED) { 122 error("failed to allocate inode\n"); 123 return EXT4_ALLOCATE_FAILED; 124 } 125 126 add_directory(inode_num); 127 128 inode = get_inode(inode_num); 129 if (inode == NULL) { 130 error("failed to get inode %u", inode_num); 131 return EXT4_ALLOCATE_FAILED; 132 } 133 134 data = inode_allocate_data_extents(inode, len, len); 135 if (data == NULL) { 136 error("failed to allocate %u extents", len); 137 return EXT4_ALLOCATE_FAILED; 138 } 139 140 inode->i_mode = S_IFDIR; 141 inode->i_links_count = dirs + 2; 142 inode->i_flags |= aux_info.default_i_flags; 143 144 dentry = NULL; 145 146 dentry = add_dentry(data, &offset, NULL, inode_num, ".", EXT4_FT_DIR); 147 if (!dentry) { 148 error("failed to add . directory"); 149 return EXT4_ALLOCATE_FAILED; 150 } 151 152 dentry = add_dentry(data, &offset, dentry, dir_inode_num, "..", EXT4_FT_DIR); 153 if (!dentry) { 154 error("failed to add .. directory"); 155 return EXT4_ALLOCATE_FAILED; 156 } 157 158 for (i = 0; i < entries; i++) { 159 dentry = add_dentry(data, &offset, dentry, 0, 160 dentries[i].filename, dentries[i].file_type); 161 if (offset > len || (offset == len && i != entries - 1)) 162 critical_error("internal error: dentry for %s ends at %d, past %d\n", 163 dentries[i].filename, offset, len); 164 dentries[i].inode = &dentry->inode; 165 if (!dentry) { 166 error("failed to add directory"); 167 return EXT4_ALLOCATE_FAILED; 168 } 169 } 170 171 /* pad the last dentry out to the end of the block */ 172 dentry->rec_len += len - offset; 173 174 return inode_num; 175} 176 177/* Creates a file on disk. Returns the inode number of the new file */ 178u32 make_file(const char *filename, u64 len) 179{ 180 struct ext4_inode *inode; 181 u32 inode_num; 182 183 inode_num = allocate_inode(info); 184 if (inode_num == EXT4_ALLOCATE_FAILED) { 185 error("failed to allocate inode\n"); 186 return EXT4_ALLOCATE_FAILED; 187 } 188 189 inode = get_inode(inode_num); 190 if (inode == NULL) { 191 error("failed to get inode %u", inode_num); 192 return EXT4_ALLOCATE_FAILED; 193 } 194 195 if (len > 0) { 196 struct block_allocation* alloc = inode_allocate_file_extents(inode, len, filename); 197 if (alloc) { 198 alloc->filename = strdup(filename); 199 alloc->next = saved_allocation_head; 200 saved_allocation_head = alloc; 201 } 202 } 203 204 inode->i_mode = S_IFREG; 205 inode->i_links_count = 1; 206 inode->i_flags |= aux_info.default_i_flags; 207 208 return inode_num; 209} 210 211/* Creates a file on disk. Returns the inode number of the new file */ 212u32 make_link(const char *link) 213{ 214 struct ext4_inode *inode; 215 u32 inode_num; 216 u32 len = strlen(link); 217 218 inode_num = allocate_inode(info); 219 if (inode_num == EXT4_ALLOCATE_FAILED) { 220 error("failed to allocate inode\n"); 221 return EXT4_ALLOCATE_FAILED; 222 } 223 224 inode = get_inode(inode_num); 225 if (inode == NULL) { 226 error("failed to get inode %u", inode_num); 227 return EXT4_ALLOCATE_FAILED; 228 } 229 230 inode->i_mode = S_IFLNK; 231 inode->i_links_count = 1; 232 inode->i_flags |= aux_info.default_i_flags; 233 inode->i_size_lo = len; 234 235 if (len + 1 <= sizeof(inode->i_block)) { 236 /* Fast symlink */ 237 memcpy((char*)inode->i_block, link, len); 238 } else { 239 u8 *data = inode_allocate_data_indirect(inode, info.block_size, info.block_size); 240 memcpy(data, link, len); 241 inode->i_blocks_lo = info.block_size / 512; 242 } 243 244 return inode_num; 245} 246 247int inode_set_permissions(u32 inode_num, u16 mode, u16 uid, u16 gid, u32 mtime) 248{ 249 struct ext4_inode *inode = get_inode(inode_num); 250 251 if (!inode) 252 return -1; 253 254 inode->i_mode |= mode; 255 inode->i_uid = uid; 256 inode->i_gid = gid; 257 inode->i_mtime = mtime; 258 inode->i_atime = mtime; 259 inode->i_ctime = mtime; 260 261 return 0; 262} 263 264/* 265 * Returns the amount of free space available in the specified 266 * xattr region 267 */ 268static size_t xattr_free_space(struct ext4_xattr_entry *entry, char *end) 269{ 270 while(!IS_LAST_ENTRY(entry) && (((char *) entry) < end)) { 271 end -= EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)); 272 entry = EXT4_XATTR_NEXT(entry); 273 } 274 275 if (((char *) entry) > end) { 276 error("unexpected read beyond end of xattr space"); 277 return 0; 278 } 279 280 return end - ((char *) entry); 281} 282 283/* 284 * Returns a pointer to the free space immediately after the 285 * last xattr element 286 */ 287static struct ext4_xattr_entry* xattr_get_last(struct ext4_xattr_entry *entry) 288{ 289 for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { 290 // skip entry 291 } 292 return entry; 293} 294 295/* 296 * assert that the elements in the ext4 xattr section are in sorted order 297 * 298 * The ext4 filesystem requires extended attributes to be sorted when 299 * they're not stored in the inode. The kernel ext4 code uses the following 300 * sorting algorithm: 301 * 302 * 1) First sort extended attributes by their name_index. For example, 303 * EXT4_XATTR_INDEX_USER (1) comes before EXT4_XATTR_INDEX_SECURITY (6). 304 * 2) If the name_indexes are equal, then sorting is based on the length 305 * of the name. For example, XATTR_SELINUX_SUFFIX ("selinux") comes before 306 * XATTR_CAPS_SUFFIX ("capability") because "selinux" is shorter than "capability" 307 * 3) If the name_index and name_length are equal, then memcmp() is used to determine 308 * which name comes first. For example, "selinux" would come before "yelinux". 309 * 310 * This method is intended to implement the sorting function defined in 311 * the Linux kernel file fs/ext4/xattr.c function ext4_xattr_find_entry(). 312 */ 313static void xattr_assert_sane(struct ext4_xattr_entry *entry) 314{ 315 for( ; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { 316 struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(entry); 317 if (IS_LAST_ENTRY(next)) { 318 return; 319 } 320 321 int cmp = next->e_name_index - entry->e_name_index; 322 if (cmp == 0) 323 cmp = next->e_name_len - entry->e_name_len; 324 if (cmp == 0) 325 cmp = memcmp(next->e_name, entry->e_name, next->e_name_len); 326 if (cmp < 0) { 327 error("BUG: extended attributes are not sorted\n"); 328 return; 329 } 330 if (cmp == 0) { 331 error("BUG: duplicate extended attributes detected\n"); 332 return; 333 } 334 } 335} 336 337#define NAME_HASH_SHIFT 5 338#define VALUE_HASH_SHIFT 16 339 340static void ext4_xattr_hash_entry(struct ext4_xattr_header *header, 341 struct ext4_xattr_entry *entry) 342{ 343 u32 hash = 0; 344 char *name = entry->e_name; 345 int n; 346 347 for (n = 0; n < entry->e_name_len; n++) { 348 hash = (hash << NAME_HASH_SHIFT) ^ 349 (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ 350 *name++; 351 } 352 353 if (entry->e_value_block == 0 && entry->e_value_size != 0) { 354 u32 *value = (u32 *)((char *)header + 355 le16_to_cpu(entry->e_value_offs)); 356 for (n = (le32_to_cpu(entry->e_value_size) + 357 EXT4_XATTR_ROUND) >> EXT4_XATTR_PAD_BITS; n; n--) { 358 hash = (hash << VALUE_HASH_SHIFT) ^ 359 (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ 360 le32_to_cpu(*value++); 361 } 362 } 363 entry->e_hash = cpu_to_le32(hash); 364} 365 366#undef NAME_HASH_SHIFT 367#undef VALUE_HASH_SHIFT 368 369static struct ext4_xattr_entry* xattr_addto_range( 370 void *block_start, 371 void *block_end, 372 struct ext4_xattr_entry *first, 373 int name_index, 374 const char *name, 375 const void *value, 376 size_t value_len) 377{ 378 size_t name_len = strlen(name); 379 if (name_len > 255) 380 return NULL; 381 382 size_t available_size = xattr_free_space(first, block_end); 383 size_t needed_size = EXT4_XATTR_LEN(name_len) + EXT4_XATTR_SIZE(value_len); 384 385 if (needed_size > available_size) 386 return NULL; 387 388 struct ext4_xattr_entry *new_entry = xattr_get_last(first); 389 memset(new_entry, 0, EXT4_XATTR_LEN(name_len)); 390 391 new_entry->e_name_len = name_len; 392 new_entry->e_name_index = name_index; 393 memcpy(new_entry->e_name, name, name_len); 394 new_entry->e_value_block = 0; 395 new_entry->e_value_size = cpu_to_le32(value_len); 396 397 char *val = (char *) new_entry + available_size - EXT4_XATTR_SIZE(value_len); 398 size_t e_value_offs = val - (char *) block_start; 399 400 new_entry->e_value_offs = cpu_to_le16(e_value_offs); 401 memset(val, 0, EXT4_XATTR_SIZE(value_len)); 402 memcpy(val, value, value_len); 403 404 xattr_assert_sane(first); 405 return new_entry; 406} 407 408static int xattr_addto_inode(struct ext4_inode *inode, int name_index, 409 const char *name, const void *value, size_t value_len) 410{ 411 struct ext4_xattr_ibody_header *hdr = (struct ext4_xattr_ibody_header *) (inode + 1); 412 struct ext4_xattr_entry *first = (struct ext4_xattr_entry *) (hdr + 1); 413 char *block_end = ((char *) inode) + info.inode_size; 414 415 struct ext4_xattr_entry *result = 416 xattr_addto_range(first, block_end, first, name_index, name, value, value_len); 417 418 if (result == NULL) 419 return -1; 420 421 hdr->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); 422 inode->i_extra_isize = cpu_to_le16(sizeof(struct ext4_inode) - EXT4_GOOD_OLD_INODE_SIZE); 423 424 return 0; 425} 426 427static int xattr_addto_block(struct ext4_inode *inode, int name_index, 428 const char *name, const void *value, size_t value_len) 429{ 430 struct ext4_xattr_header *header = get_xattr_block_for_inode(inode); 431 if (!header) 432 return -1; 433 434 struct ext4_xattr_entry *first = (struct ext4_xattr_entry *) (header + 1); 435 char *block_end = ((char *) header) + info.block_size; 436 437 struct ext4_xattr_entry *result = 438 xattr_addto_range(header, block_end, first, name_index, name, value, value_len); 439 440 if (result == NULL) 441 return -1; 442 443 ext4_xattr_hash_entry(header, result); 444 return 0; 445} 446 447 448static int xattr_add(u32 inode_num, int name_index, const char *name, 449 const void *value, size_t value_len) 450{ 451 if (!value) 452 return 0; 453 454 struct ext4_inode *inode = get_inode(inode_num); 455 456 if (!inode) 457 return -1; 458 459 int result = xattr_addto_inode(inode, name_index, name, value, value_len); 460 if (result != 0) { 461 result = xattr_addto_block(inode, name_index, name, value, value_len); 462 } 463 return result; 464} 465 466int inode_set_selinux(u32 inode_num, const char *secon) 467{ 468 if (!secon) 469 return 0; 470 471 return xattr_add(inode_num, EXT4_XATTR_INDEX_SECURITY, 472 XATTR_SELINUX_SUFFIX, secon, strlen(secon) + 1); 473} 474 475int inode_set_capabilities(u32 inode_num, uint64_t capabilities) { 476 if (capabilities == 0) 477 return 0; 478 479 struct vfs_cap_data cap_data; 480 memset(&cap_data, 0, sizeof(cap_data)); 481 482 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; 483 cap_data.data[0].permitted = (uint32_t) (capabilities & 0xffffffff); 484 cap_data.data[0].inheritable = 0; 485 cap_data.data[1].permitted = (uint32_t) (capabilities >> 32); 486 cap_data.data[1].inheritable = 0; 487 488 return xattr_add(inode_num, EXT4_XATTR_INDEX_SECURITY, 489 XATTR_CAPS_SUFFIX, &cap_data, sizeof(cap_data)); 490} 491