1 /* 2 * ext_attr.c --- extended attribute blocks 3 * 4 * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher (at) computer.org> 5 * 6 * Copyright (C) 2002 Theodore Ts'o. 7 * 8 * %Begin-Header% 9 * This file may be redistributed under the terms of the GNU Library 10 * General Public License, version 2. 11 * %End-Header% 12 */ 13 14 #include "config.h" 15 #include <stdio.h> 16 #if HAVE_UNISTD_H 17 #include <unistd.h> 18 #endif 19 #include <string.h> 20 #include <time.h> 21 22 #include "ext2_fs.h" 23 #include "ext2_ext_attr.h" 24 #include "ext4_acl.h" 25 26 #include "ext2fs.h" 27 28 static errcode_t read_ea_inode_hash(ext2_filsys fs, ext2_ino_t ino, __u32 *hash) 29 { 30 struct ext2_inode inode; 31 errcode_t retval; 32 33 retval = ext2fs_read_inode(fs, ino, &inode); 34 if (retval) 35 return retval; 36 *hash = ext2fs_get_ea_inode_hash(&inode); 37 return 0; 38 } 39 40 #define NAME_HASH_SHIFT 5 41 #define VALUE_HASH_SHIFT 16 42 43 /* 44 * ext2_xattr_hash_entry() 45 * 46 * Compute the hash of an extended attribute. 47 */ 48 __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry, void *data) 49 { 50 __u32 hash = 0; 51 char *name = ((char *) entry) + sizeof(struct ext2_ext_attr_entry); 52 int n; 53 54 for (n = 0; n < entry->e_name_len; n++) { 55 hash = (hash << NAME_HASH_SHIFT) ^ 56 (hash >> (8*sizeof(hash) - NAME_HASH_SHIFT)) ^ 57 *name++; 58 } 59 60 /* The hash needs to be calculated on the data in little-endian. */ 61 if (entry->e_value_inum == 0 && entry->e_value_size != 0) { 62 __u32 *value = (__u32 *)data; 63 for (n = (entry->e_value_size + EXT2_EXT_ATTR_ROUND) >> 64 EXT2_EXT_ATTR_PAD_BITS; n; n--) { 65 hash = (hash << VALUE_HASH_SHIFT) ^ 66 (hash >> (8*sizeof(hash) - VALUE_HASH_SHIFT)) ^ 67 ext2fs_le32_to_cpu(*value++); 68 } 69 } 70 71 return hash; 72 } 73 74 /* 75 * ext2fs_ext_attr_hash_entry2() 76 * 77 * Compute the hash of an extended attribute. 78 * This version of the function supports hashing entries that reference 79 * external inodes (ea_inode feature). 80 */ 81 errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs, 82 struct ext2_ext_attr_entry *entry, 83 void *data, __u32 *hash) 84 { 85 *hash = ext2fs_ext_attr_hash_entry(entry, data); 86 87 if (entry->e_value_inum) { 88 __u32 ea_inode_hash; 89 errcode_t retval; 90 91 retval = read_ea_inode_hash(fs, entry->e_value_inum, 92 &ea_inode_hash); 93 if (retval) 94 return retval; 95 96 *hash = (*hash << VALUE_HASH_SHIFT) ^ 97 (*hash >> (8*sizeof(*hash) - VALUE_HASH_SHIFT)) ^ 98 ea_inode_hash; 99 } 100 return 0; 101 } 102 103 #undef NAME_HASH_SHIFT 104 #undef VALUE_HASH_SHIFT 105 106 #define BLOCK_HASH_SHIFT 16 107 108 /* Mirrors ext4_xattr_rehash() implementation in kernel. */ 109 void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header, 110 struct ext2_ext_attr_entry *end) 111 { 112 struct ext2_ext_attr_entry *here; 113 __u32 hash = 0; 114 115 here = (struct ext2_ext_attr_entry *)(header+1); 116 while (here < end && !EXT2_EXT_IS_LAST_ENTRY(here)) { 117 if (!here->e_hash) { 118 /* Block is not shared if an entry's hash value == 0 */ 119 hash = 0; 120 break; 121 } 122 hash = (hash << BLOCK_HASH_SHIFT) ^ 123 (hash >> (8*sizeof(hash) - BLOCK_HASH_SHIFT)) ^ 124 here->e_hash; 125 here = EXT2_EXT_ATTR_NEXT(here); 126 } 127 header->h_hash = hash; 128 } 129 130 #undef BLOCK_HASH_SHIFT 131 132 __u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode) 133 { 134 return inode->i_atime; 135 } 136 137 void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash) 138 { 139 inode->i_atime = hash; 140 } 141 142 __u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode) 143 { 144 return ((__u64)inode->i_ctime << 32) | inode->osd1.linux1.l_i_version; 145 } 146 147 void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count) 148 { 149 inode->i_ctime = (__u32)(ref_count >> 32); 150 inode->osd1.linux1.l_i_version = (__u32)ref_count; 151 } 152 153 static errcode_t check_ext_attr_header(struct ext2_ext_attr_header *header) 154 { 155 if ((header->h_magic != EXT2_EXT_ATTR_MAGIC_v1 && 156 header->h_magic != EXT2_EXT_ATTR_MAGIC) || 157 header->h_blocks != 1) 158 return EXT2_ET_BAD_EA_HEADER; 159 160 return 0; 161 } 162 163 errcode_t ext2fs_read_ext_attr3(ext2_filsys fs, blk64_t block, void *buf, 164 ext2_ino_t inum) 165 { 166 int csum_failed = 0; 167 errcode_t retval; 168 169 retval = io_channel_read_blk64(fs->io, block, 1, buf); 170 if (retval) 171 return retval; 172 173 if (!(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS) && 174 !ext2fs_ext_attr_block_csum_verify(fs, inum, block, buf)) 175 csum_failed = 1; 176 177 #ifdef WORDS_BIGENDIAN 178 ext2fs_swap_ext_attr(buf, buf, fs->blocksize, 1); 179 #endif 180 181 retval = check_ext_attr_header(buf); 182 if (retval == 0 && csum_failed) 183 retval = EXT2_ET_EXT_ATTR_CSUM_INVALID; 184 185 return retval; 186 } 187 188 errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block, void *buf) 189 { 190 return ext2fs_read_ext_attr3(fs, block, buf, 0); 191 } 192 193 errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf) 194 { 195 return ext2fs_read_ext_attr2(fs, block, buf); 196 } 197 198 errcode_t ext2fs_write_ext_attr3(ext2_filsys fs, blk64_t block, void *inbuf, 199 ext2_ino_t inum) 200 { 201 errcode_t retval; 202 char *write_buf; 203 204 #ifdef WORDS_BIGENDIAN 205 retval = ext2fs_get_mem(fs->blocksize, &write_buf); 206 if (retval) 207 return retval; 208 ext2fs_swap_ext_attr(write_buf, inbuf, fs->blocksize, 1); 209 #else 210 write_buf = (char *) inbuf; 211 #endif 212 213 retval = ext2fs_ext_attr_block_csum_set(fs, inum, block, 214 (struct ext2_ext_attr_header *)write_buf); 215 if (retval) 216 return retval; 217 218 retval = io_channel_write_blk64(fs->io, block, 1, write_buf); 219 #ifdef WORDS_BIGENDIAN 220 ext2fs_free_mem(&write_buf); 221 #endif 222 if (!retval) 223 ext2fs_mark_changed(fs); 224 return retval; 225 } 226 227 errcode_t ext2fs_write_ext_attr2(ext2_filsys fs, blk64_t block, void *inbuf) 228 { 229 return ext2fs_write_ext_attr3(fs, block, inbuf, 0); 230 } 231 232 errcode_t ext2fs_write_ext_attr(ext2_filsys fs, blk_t block, void *inbuf) 233 { 234 return ext2fs_write_ext_attr2(fs, block, inbuf); 235 } 236 237 /* 238 * This function adjusts the reference count of the EA block. 239 */ 240 errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk, 241 char *block_buf, int adjust, 242 __u32 *newcount, ext2_ino_t inum) 243 { 244 errcode_t retval; 245 struct ext2_ext_attr_header *header; 246 char *buf = 0; 247 248 if ((blk >= ext2fs_blocks_count(fs->super)) || 249 (blk < fs->super->s_first_data_block)) 250 return EXT2_ET_BAD_EA_BLOCK_NUM; 251 252 if (!block_buf) { 253 retval = ext2fs_get_mem(fs->blocksize, &buf); 254 if (retval) 255 return retval; 256 block_buf = buf; 257 } 258 259 retval = ext2fs_read_ext_attr3(fs, blk, block_buf, inum); 260 if (retval) 261 goto errout; 262 263 header = (struct ext2_ext_attr_header *) block_buf; 264 header->h_refcount += adjust; 265 if (newcount) 266 *newcount = header->h_refcount; 267 268 retval = ext2fs_write_ext_attr3(fs, blk, block_buf, inum); 269 if (retval) 270 goto errout; 271 272 errout: 273 if (buf) 274 ext2fs_free_mem(&buf); 275 return retval; 276 } 277 278 errcode_t ext2fs_adjust_ea_refcount2(ext2_filsys fs, blk64_t blk, 279 char *block_buf, int adjust, 280 __u32 *newcount) 281 { 282 return ext2fs_adjust_ea_refcount3(fs, blk, block_buf, adjust, 283 newcount, 0); 284 } 285 286 errcode_t ext2fs_adjust_ea_refcount(ext2_filsys fs, blk_t blk, 287 char *block_buf, int adjust, 288 __u32 *newcount) 289 { 290 return ext2fs_adjust_ea_refcount2(fs, blk, block_buf, adjust, 291 newcount); 292 } 293 294 /* Manipulate the contents of extended attribute regions */ 295 struct ext2_xattr { 296 char *name; 297 void *value; 298 unsigned int value_len; 299 ext2_ino_t ea_ino; 300 }; 301 302 struct ext2_xattr_handle { 303 errcode_t magic; 304 ext2_filsys fs; 305 struct ext2_xattr *attrs; 306 int capacity; 307 int count; 308 int ibody_count; 309 ext2_ino_t ino; 310 unsigned int flags; 311 }; 312 313 static errcode_t ext2fs_xattrs_expand(struct ext2_xattr_handle *h, 314 unsigned int expandby) 315 { 316 struct ext2_xattr *new_attrs; 317 errcode_t err; 318 319 err = ext2fs_get_arrayzero(h->capacity + expandby, 320 sizeof(struct ext2_xattr), &new_attrs); 321 if (err) 322 return err; 323 324 memcpy(new_attrs, h->attrs, h->capacity * sizeof(struct ext2_xattr)); 325 ext2fs_free_mem(&h->attrs); 326 h->capacity += expandby; 327 h->attrs = new_attrs; 328 329 return 0; 330 } 331 332 struct ea_name_index { 333 int index; 334 const char *name; 335 }; 336 337 /* Keep these names sorted in order of decreasing specificity. */ 338 static struct ea_name_index ea_names[] = { 339 {3, "system.posix_acl_default"}, 340 {2, "system.posix_acl_access"}, 341 {8, "system.richacl"}, 342 {6, "security."}, 343 {4, "trusted."}, 344 {7, "system."}, 345 {1, "user."}, 346 {0, NULL}, 347 }; 348 349 static const char *find_ea_prefix(int index) 350 { 351 struct ea_name_index *e; 352 353 for (e = ea_names; e->name; e++) 354 if (e->index == index) 355 return e->name; 356 357 return NULL; 358 } 359 360 static int find_ea_index(const char *fullname, const char **name, int *index) 361 { 362 struct ea_name_index *e; 363 364 for (e = ea_names; e->name; e++) { 365 if (strncmp(fullname, e->name, strlen(e->name)) == 0) { 366 *name = fullname + strlen(e->name); 367 *index = e->index; 368 return 1; 369 } 370 } 371 return 0; 372 } 373 374 errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino, 375 struct ext2_inode_large *inode) 376 { 377 struct ext2_ext_attr_header *header; 378 void *block_buf = NULL; 379 blk64_t blk; 380 errcode_t err; 381 struct ext2_inode_large i; 382 383 /* Read inode? */ 384 if (inode == NULL) { 385 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&i, 386 sizeof(struct ext2_inode_large)); 387 if (err) 388 return err; 389 inode = &i; 390 } 391 392 /* Do we already have an EA block? */ 393 blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); 394 if (blk == 0) 395 return 0; 396 397 /* Find block, zero it, write back */ 398 if ((blk < fs->super->s_first_data_block) || 399 (blk >= ext2fs_blocks_count(fs->super))) { 400 err = EXT2_ET_BAD_EA_BLOCK_NUM; 401 goto out; 402 } 403 404 err = ext2fs_get_mem(fs->blocksize, &block_buf); 405 if (err) 406 goto out; 407 408 err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino); 409 if (err) 410 goto out2; 411 412 /* We only know how to deal with v2 EA blocks */ 413 header = (struct ext2_ext_attr_header *) block_buf; 414 if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { 415 err = EXT2_ET_BAD_EA_HEADER; 416 goto out2; 417 } 418 419 header->h_refcount--; 420 err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino); 421 if (err) 422 goto out2; 423 424 /* Erase link to block */ 425 ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, 0); 426 if (header->h_refcount == 0) 427 ext2fs_block_alloc_stats2(fs, blk, -1); 428 err = ext2fs_iblk_sub_blocks(fs, (struct ext2_inode *)inode, 1); 429 if (err) 430 goto out2; 431 432 /* Write inode? */ 433 if (inode == &i) { 434 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&i, 435 sizeof(struct ext2_inode_large)); 436 if (err) 437 goto out2; 438 } 439 440 out2: 441 ext2fs_free_mem(&block_buf); 442 out: 443 return err; 444 } 445 446 static errcode_t prep_ea_block_for_write(ext2_filsys fs, ext2_ino_t ino, 447 struct ext2_inode_large *inode) 448 { 449 struct ext2_ext_attr_header *header; 450 void *block_buf = NULL; 451 blk64_t blk, goal; 452 errcode_t err; 453 454 /* Do we already have an EA block? */ 455 blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); 456 if (blk != 0) { 457 if ((blk < fs->super->s_first_data_block) || 458 (blk >= ext2fs_blocks_count(fs->super))) { 459 err = EXT2_ET_BAD_EA_BLOCK_NUM; 460 goto out; 461 } 462 463 err = ext2fs_get_mem(fs->blocksize, &block_buf); 464 if (err) 465 goto out; 466 467 err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino); 468 if (err) 469 goto out2; 470 471 /* We only know how to deal with v2 EA blocks */ 472 header = (struct ext2_ext_attr_header *) block_buf; 473 if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { 474 err = EXT2_ET_BAD_EA_HEADER; 475 goto out2; 476 } 477 478 /* Single-user block. We're done here. */ 479 if (header->h_refcount == 1) 480 goto out2; 481 482 /* We need to CoW the block. */ 483 header->h_refcount--; 484 err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino); 485 if (err) 486 goto out2; 487 } else { 488 /* No block, we must increment i_blocks */ 489 err = ext2fs_iblk_add_blocks(fs, (struct ext2_inode *)inode, 490 1); 491 if (err) 492 goto out; 493 } 494 495 /* Allocate a block */ 496 goal = ext2fs_find_inode_goal(fs, ino, (struct ext2_inode *)inode, 0); 497 err = ext2fs_alloc_block2(fs, goal, NULL, &blk); 498 if (err) 499 goto out2; 500 ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, blk); 501 out2: 502 if (block_buf) 503 ext2fs_free_mem(&block_buf); 504 out: 505 return err; 506 } 507 508 509 static inline int 510 posix_acl_xattr_count(size_t size) 511 { 512 if (size < sizeof(posix_acl_xattr_header)) 513 return -1; 514 size -= sizeof(posix_acl_xattr_header); 515 if (size % sizeof(posix_acl_xattr_entry)) 516 return -1; 517 return size / sizeof(posix_acl_xattr_entry); 518 } 519 520 /* 521 * The lgetxattr function returns data formatted in the POSIX extended 522 * attribute format. The on-disk format uses a more compact encoding. 523 * See the ext4_acl_to_disk in fs/ext4/acl.c. 524 */ 525 static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size, 526 void *out_buf, size_t *size_out) 527 { 528 const posix_acl_xattr_header *header = 529 (const posix_acl_xattr_header*) value; 530 const posix_acl_xattr_entry *end, *entry = 531 (const posix_acl_xattr_entry *)(header+1); 532 ext4_acl_header *ext_acl; 533 size_t s; 534 char *e; 535 536 int count; 537 538 if (!value) 539 return EINVAL; 540 if (size < sizeof(posix_acl_xattr_header)) 541 return ENOMEM; 542 if (header->a_version != ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 543 return EINVAL; 544 545 count = posix_acl_xattr_count(size); 546 ext_acl = out_buf; 547 ext_acl->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION); 548 549 if (count <= 0) 550 return EINVAL; 551 552 e = (char *) out_buf + sizeof(ext4_acl_header); 553 s = sizeof(ext4_acl_header); 554 for (end = entry + count; entry != end;entry++) { 555 ext4_acl_entry *disk_entry = (ext4_acl_entry*) e; 556 disk_entry->e_tag = ext2fs_cpu_to_le16(entry->e_tag); 557 disk_entry->e_perm = ext2fs_cpu_to_le16(entry->e_perm); 558 559 switch(entry->e_tag) { 560 case ACL_USER_OBJ: 561 case ACL_GROUP_OBJ: 562 case ACL_MASK: 563 case ACL_OTHER: 564 e += sizeof(ext4_acl_entry_short); 565 s += sizeof(ext4_acl_entry_short); 566 break; 567 case ACL_USER: 568 case ACL_GROUP: 569 disk_entry->e_id = ext2fs_cpu_to_le32(entry->e_id); 570 e += sizeof(ext4_acl_entry); 571 s += sizeof(ext4_acl_entry); 572 break; 573 } 574 } 575 *size_out = s; 576 return 0; 577 } 578 579 static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size, 580 void **out_buf, size_t *size_out) 581 { 582 posix_acl_xattr_header *header; 583 posix_acl_xattr_entry *entry; 584 const ext4_acl_header *ext_acl = (const ext4_acl_header *) value; 585 errcode_t err; 586 const char *cp; 587 char *out; 588 589 if ((!value) || 590 (size < sizeof(ext4_acl_header)) || 591 (ext_acl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))) 592 return EINVAL; 593 594 err = ext2fs_get_mem(size * 2, &out); 595 if (err) 596 return err; 597 598 header = (posix_acl_xattr_header *) out; 599 header->a_version = ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION); 600 entry = (posix_acl_xattr_entry *) (out + sizeof(posix_acl_xattr_header)); 601 602 cp = (const char *) value + sizeof(ext4_acl_header); 603 size -= sizeof(ext4_acl_header); 604 605 while (size > 0) { 606 const ext4_acl_entry *disk_entry = (const ext4_acl_entry *) cp; 607 608 entry->e_tag = ext2fs_le16_to_cpu(disk_entry->e_tag); 609 entry->e_perm = ext2fs_le16_to_cpu(disk_entry->e_perm); 610 611 switch(entry->e_tag) { 612 case ACL_USER_OBJ: 613 case ACL_GROUP_OBJ: 614 case ACL_MASK: 615 case ACL_OTHER: 616 entry->e_id = 0; 617 cp += sizeof(ext4_acl_entry_short); 618 size -= sizeof(ext4_acl_entry_short); 619 break; 620 case ACL_USER: 621 case ACL_GROUP: 622 entry->e_id = ext2fs_le32_to_cpu(disk_entry->e_id); 623 cp += sizeof(ext4_acl_entry); 624 size -= sizeof(ext4_acl_entry); 625 break; 626 default: 627 ext2fs_free_mem(&out); 628 return EINVAL; 629 break; 630 } 631 entry++; 632 } 633 *out_buf = out; 634 *size_out = ((char *) entry - out); 635 return 0; 636 } 637 638 static errcode_t 639 write_xattrs_to_buffer(ext2_filsys fs, struct ext2_xattr *attrs, int count, 640 void *entries_start, unsigned int storage_size, 641 unsigned int value_offset_correction, int write_hash) 642 { 643 struct ext2_xattr *x; 644 struct ext2_ext_attr_entry *e = entries_start; 645 char *end = (char *) entries_start + storage_size; 646 const char *shortname; 647 unsigned int value_size; 648 int idx, ret; 649 errcode_t err; 650 651 memset(entries_start, 0, storage_size); 652 for (x = attrs; x < attrs + count; x++) { 653 /* Calculate index and shortname position */ 654 shortname = x->name; 655 ret = find_ea_index(x->name, &shortname, &idx); 656 657 value_size = ((x->value_len + EXT2_EXT_ATTR_PAD - 1) / 658 EXT2_EXT_ATTR_PAD) * EXT2_EXT_ATTR_PAD; 659 660 /* Fill out e appropriately */ 661 e->e_name_len = strlen(shortname); 662 e->e_name_index = (ret ? idx : 0); 663 664 e->e_value_size = x->value_len; 665 e->e_value_inum = x->ea_ino; 666 667 /* Store name */ 668 memcpy((char *)e + sizeof(*e), shortname, e->e_name_len); 669 if (x->ea_ino) { 670 e->e_value_offs = 0; 671 } else { 672 end -= value_size; 673 e->e_value_offs = end - (char *) entries_start + 674 value_offset_correction; 675 memcpy(end, x->value, e->e_value_size); 676 } 677 678 if (write_hash || x->ea_ino) { 679 err = ext2fs_ext_attr_hash_entry2(fs, e, 680 x->ea_ino ? 0 : end, 681 &e->e_hash); 682 if (err) 683 return err; 684 } else 685 e->e_hash = 0; 686 687 e = EXT2_EXT_ATTR_NEXT(e); 688 *(__u32 *)e = 0; 689 } 690 return 0; 691 } 692 693 errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle) 694 { 695 ext2_filsys fs = handle->fs; 696 const unsigned int inode_size = EXT2_INODE_SIZE(fs->super); 697 struct ext2_inode_large *inode; 698 char *start, *block_buf = NULL; 699 struct ext2_ext_attr_header *header; 700 __u32 ea_inode_magic; 701 blk64_t blk; 702 unsigned int storage_size; 703 unsigned int i; 704 errcode_t err; 705 706 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 707 i = inode_size; 708 if (i < sizeof(*inode)) 709 i = sizeof(*inode); 710 err = ext2fs_get_memzero(i, &inode); 711 if (err) 712 return err; 713 714 err = ext2fs_read_inode_full(fs, handle->ino, EXT2_INODE(inode), 715 inode_size); 716 if (err) 717 goto out; 718 719 /* If extra_isize isn't set, we need to set it now */ 720 if (inode->i_extra_isize == 0 && 721 inode_size > EXT2_GOOD_OLD_INODE_SIZE) { 722 char *p = (char *)inode; 723 size_t extra = fs->super->s_want_extra_isize; 724 725 if (extra == 0) 726 extra = sizeof(__u32); 727 memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra); 728 inode->i_extra_isize = extra; 729 } 730 if (inode->i_extra_isize & 3) { 731 err = EXT2_ET_INODE_CORRUPTED; 732 goto out; 733 } 734 735 /* Does the inode have space for EA? */ 736 if (inode->i_extra_isize < sizeof(inode->i_extra_isize) || 737 inode_size <= EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize + 738 sizeof(__u32)) 739 goto write_ea_block; 740 741 /* Write the inode EA */ 742 ea_inode_magic = EXT2_EXT_ATTR_MAGIC; 743 memcpy(((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 744 inode->i_extra_isize, &ea_inode_magic, sizeof(__u32)); 745 storage_size = inode_size - EXT2_GOOD_OLD_INODE_SIZE - 746 inode->i_extra_isize - sizeof(__u32); 747 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 748 inode->i_extra_isize + sizeof(__u32); 749 750 err = write_xattrs_to_buffer(fs, handle->attrs, handle->ibody_count, 751 start, storage_size, 0, 0); 752 if (err) 753 goto out; 754 write_ea_block: 755 /* Are we done? */ 756 if (handle->ibody_count == handle->count && 757 !ext2fs_file_acl_block(fs, EXT2_INODE(inode))) 758 goto skip_ea_block; 759 760 /* Write the EA block */ 761 err = ext2fs_get_memzero(fs->blocksize, &block_buf); 762 if (err) 763 goto out; 764 765 storage_size = fs->blocksize - sizeof(struct ext2_ext_attr_header); 766 start = block_buf + sizeof(struct ext2_ext_attr_header); 767 768 err = write_xattrs_to_buffer(fs, handle->attrs + handle->ibody_count, 769 handle->count - handle->ibody_count, start, 770 storage_size, start - block_buf, 1); 771 if (err) 772 goto out2; 773 774 /* Write a header on the EA block */ 775 header = (struct ext2_ext_attr_header *) block_buf; 776 header->h_magic = EXT2_EXT_ATTR_MAGIC; 777 header->h_refcount = 1; 778 header->h_blocks = 1; 779 780 /* Get a new block for writing */ 781 err = prep_ea_block_for_write(fs, handle->ino, inode); 782 if (err) 783 goto out2; 784 785 /* Finally, write the new EA block */ 786 blk = ext2fs_file_acl_block(fs, EXT2_INODE(inode)); 787 err = ext2fs_write_ext_attr3(fs, blk, block_buf, handle->ino); 788 if (err) 789 goto out2; 790 791 skip_ea_block: 792 blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); 793 if (!block_buf && blk) { 794 /* xattrs shrunk, free the block */ 795 err = ext2fs_free_ext_attr(fs, handle->ino, inode); 796 if (err) 797 goto out; 798 } 799 800 /* Write the inode */ 801 err = ext2fs_write_inode_full(fs, handle->ino, EXT2_INODE(inode), 802 inode_size); 803 if (err) 804 goto out2; 805 806 out2: 807 ext2fs_free_mem(&block_buf); 808 out: 809 ext2fs_free_mem(&inode); 810 return err; 811 } 812 813 static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle, 814 struct ext2_inode_large *inode, 815 struct ext2_ext_attr_entry *entries, 816 unsigned int storage_size, 817 char *value_start) 818 { 819 struct ext2_xattr *x; 820 struct ext2_ext_attr_entry *entry, *end; 821 const char *prefix; 822 unsigned int remain, prefix_len; 823 errcode_t err; 824 unsigned int values_size = storage_size + 825 ((char *)entries - value_start); 826 827 /* find the end */ 828 end = entries; 829 remain = storage_size; 830 while (remain >= sizeof(struct ext2_ext_attr_entry) && 831 !EXT2_EXT_IS_LAST_ENTRY(end)) { 832 833 /* header eats this space */ 834 remain -= sizeof(struct ext2_ext_attr_entry); 835 836 /* is attribute name valid? */ 837 if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain) 838 return EXT2_ET_EA_BAD_NAME_LEN; 839 840 /* attribute len eats this space */ 841 remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len); 842 end = EXT2_EXT_ATTR_NEXT(end); 843 } 844 845 entry = entries; 846 remain = storage_size; 847 while (remain >= sizeof(struct ext2_ext_attr_entry) && 848 !EXT2_EXT_IS_LAST_ENTRY(entry)) { 849 850 /* Allocate space for more attrs? */ 851 if (handle->count == handle->capacity) { 852 err = ext2fs_xattrs_expand(handle, 4); 853 if (err) 854 return err; 855 } 856 857 x = handle->attrs + handle->count; 858 859 /* header eats this space */ 860 remain -= sizeof(struct ext2_ext_attr_entry); 861 862 /* attribute len eats this space */ 863 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); 864 865 /* Extract name */ 866 prefix = find_ea_prefix(entry->e_name_index); 867 prefix_len = (prefix ? strlen(prefix) : 0); 868 err = ext2fs_get_memzero(entry->e_name_len + prefix_len + 1, 869 &x->name); 870 if (err) 871 return err; 872 if (prefix) 873 memcpy(x->name, prefix, prefix_len); 874 if (entry->e_name_len) 875 memcpy(x->name + prefix_len, 876 (char *)entry + sizeof(*entry), 877 entry->e_name_len); 878 879 /* Check & copy value */ 880 if (!ext2fs_has_feature_ea_inode(handle->fs->super) && 881 entry->e_value_inum != 0) 882 return EXT2_ET_BAD_EA_BLOCK_NUM; 883 884 if (entry->e_value_inum == 0) { 885 if (entry->e_value_size > remain) 886 return EXT2_ET_EA_BAD_VALUE_SIZE; 887 888 if (entry->e_value_offs + entry->e_value_size > values_size) 889 return EXT2_ET_EA_BAD_VALUE_OFFSET; 890 891 if (entry->e_value_size > 0 && 892 value_start + entry->e_value_offs < 893 (char *)end + sizeof(__u32)) 894 return EXT2_ET_EA_BAD_VALUE_OFFSET; 895 896 remain -= entry->e_value_size; 897 898 err = ext2fs_get_mem(entry->e_value_size, &x->value); 899 if (err) 900 return err; 901 memcpy(x->value, value_start + entry->e_value_offs, 902 entry->e_value_size); 903 } else { 904 struct ext2_inode *ea_inode; 905 ext2_file_t ea_file; 906 907 if (entry->e_value_offs != 0) 908 return EXT2_ET_EA_BAD_VALUE_OFFSET; 909 910 if (entry->e_value_size > (64 * 1024)) 911 return EXT2_ET_EA_BAD_VALUE_SIZE; 912 913 err = ext2fs_get_mem(entry->e_value_size, &x->value); 914 if (err) 915 return err; 916 917 err = ext2fs_file_open(handle->fs, entry->e_value_inum, 918 0, &ea_file); 919 if (err) 920 return err; 921 922 ea_inode = ext2fs_file_get_inode(ea_file); 923 if ((ea_inode->i_flags & EXT4_INLINE_DATA_FL) || 924 !(ea_inode->i_flags & EXT4_EA_INODE_FL) || 925 ea_inode->i_links_count == 0) 926 err = EXT2_ET_EA_INODE_CORRUPTED; 927 else if (ext2fs_file_get_size(ea_file) != 928 entry->e_value_size) 929 err = EXT2_ET_EA_BAD_VALUE_SIZE; 930 else 931 err = ext2fs_file_read(ea_file, x->value, 932 entry->e_value_size, 0); 933 ext2fs_file_close(ea_file); 934 if (err) 935 return err; 936 } 937 938 x->ea_ino = entry->e_value_inum; 939 x->value_len = entry->e_value_size; 940 941 /* e_hash may be 0 in older inode's ea */ 942 if (entry->e_hash != 0) { 943 __u32 hash; 944 void *data = (entry->e_value_inum != 0) ? 945 0 : value_start + entry->e_value_offs; 946 947 err = ext2fs_ext_attr_hash_entry2(handle->fs, entry, 948 data, &hash); 949 if (err) 950 return err; 951 if (entry->e_hash != hash) { 952 struct ext2_inode child; 953 954 /* Check whether this is an old Lustre-style 955 * ea_inode reference. 956 */ 957 err = ext2fs_read_inode(handle->fs, 958 entry->e_value_inum, 959 &child); 960 if (err) 961 return err; 962 if (child.i_mtime != handle->ino || 963 child.i_generation != inode->i_generation) 964 return EXT2_ET_BAD_EA_HASH; 965 } 966 } 967 968 handle->count++; 969 entry = EXT2_EXT_ATTR_NEXT(entry); 970 } 971 972 return 0; 973 } 974 975 static void xattrs_free_keys(struct ext2_xattr_handle *h) 976 { 977 struct ext2_xattr *a = h->attrs; 978 int i; 979 980 for (i = 0; i < h->capacity; i++) { 981 if (a[i].name) 982 ext2fs_free_mem(&a[i].name); 983 if (a[i].value) 984 ext2fs_free_mem(&a[i].value); 985 } 986 h->count = 0; 987 h->ibody_count = 0; 988 } 989 990 errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle) 991 { 992 struct ext2_inode_large *inode; 993 struct ext2_ext_attr_header *header; 994 __u32 ea_inode_magic; 995 unsigned int storage_size; 996 char *start, *block_buf = NULL; 997 blk64_t blk; 998 size_t i; 999 errcode_t err; 1000 1001 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1002 i = EXT2_INODE_SIZE(handle->fs->super); 1003 if (i < sizeof(*inode)) 1004 i = sizeof(*inode); 1005 err = ext2fs_get_memzero(i, &inode); 1006 if (err) 1007 return err; 1008 1009 err = ext2fs_read_inode_full(handle->fs, handle->ino, 1010 (struct ext2_inode *)inode, 1011 EXT2_INODE_SIZE(handle->fs->super)); 1012 if (err) 1013 goto out; 1014 1015 xattrs_free_keys(handle); 1016 1017 /* Does the inode have space for EA? */ 1018 if (inode->i_extra_isize < sizeof(inode->i_extra_isize) || 1019 EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE + 1020 inode->i_extra_isize + 1021 sizeof(__u32)) 1022 goto read_ea_block; 1023 if (inode->i_extra_isize & 3) { 1024 err = EXT2_ET_INODE_CORRUPTED; 1025 goto out; 1026 } 1027 1028 /* Look for EA in the inode */ 1029 memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1030 inode->i_extra_isize, sizeof(__u32)); 1031 if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) { 1032 storage_size = EXT2_INODE_SIZE(handle->fs->super) - 1033 EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize - 1034 sizeof(__u32); 1035 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1036 inode->i_extra_isize + sizeof(__u32); 1037 1038 err = read_xattrs_from_buffer(handle, inode, 1039 (struct ext2_ext_attr_entry *) start, 1040 storage_size, start); 1041 if (err) 1042 goto out; 1043 1044 handle->ibody_count = handle->count; 1045 } 1046 1047 read_ea_block: 1048 /* Look for EA in a separate EA block */ 1049 blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode); 1050 if (blk != 0) { 1051 if ((blk < handle->fs->super->s_first_data_block) || 1052 (blk >= ext2fs_blocks_count(handle->fs->super))) { 1053 err = EXT2_ET_BAD_EA_BLOCK_NUM; 1054 goto out; 1055 } 1056 1057 err = ext2fs_get_mem(handle->fs->blocksize, &block_buf); 1058 if (err) 1059 goto out; 1060 1061 err = ext2fs_read_ext_attr3(handle->fs, blk, block_buf, 1062 handle->ino); 1063 if (err) 1064 goto out3; 1065 1066 /* We only know how to deal with v2 EA blocks */ 1067 header = (struct ext2_ext_attr_header *) block_buf; 1068 if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { 1069 err = EXT2_ET_BAD_EA_HEADER; 1070 goto out3; 1071 } 1072 1073 /* Read EAs */ 1074 storage_size = handle->fs->blocksize - 1075 sizeof(struct ext2_ext_attr_header); 1076 start = block_buf + sizeof(struct ext2_ext_attr_header); 1077 err = read_xattrs_from_buffer(handle, inode, 1078 (struct ext2_ext_attr_entry *) start, 1079 storage_size, block_buf); 1080 if (err) 1081 goto out3; 1082 1083 ext2fs_free_mem(&block_buf); 1084 } 1085 1086 ext2fs_free_mem(&block_buf); 1087 ext2fs_free_mem(&inode); 1088 return 0; 1089 1090 out3: 1091 ext2fs_free_mem(&block_buf); 1092 out: 1093 ext2fs_free_mem(&inode); 1094 return err; 1095 } 1096 1097 errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h, 1098 int (*func)(char *name, char *value, 1099 size_t value_len, void *data), 1100 void *data) 1101 { 1102 struct ext2_xattr *x; 1103 int dirty = 0; 1104 int ret; 1105 1106 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1107 for (x = h->attrs; x < h->attrs + h->count; x++) { 1108 ret = func(x->name, x->value, x->value_len, data); 1109 if (ret & XATTR_CHANGED) 1110 dirty = 1; 1111 if (ret & XATTR_ABORT) 1112 break; 1113 } 1114 1115 if (dirty) 1116 return ext2fs_xattrs_write(h); 1117 return 0; 1118 } 1119 1120 errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key, 1121 void **value, size_t *value_len) 1122 { 1123 struct ext2_xattr *x; 1124 char *val; 1125 errcode_t err; 1126 1127 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1128 for (x = h->attrs; x < h->attrs + h->count; x++) { 1129 if (strcmp(x->name, key)) 1130 continue; 1131 1132 if (!(h->flags & XATTR_HANDLE_FLAG_RAW) && 1133 ((strcmp(key, "system.posix_acl_default") == 0) || 1134 (strcmp(key, "system.posix_acl_access") == 0))) { 1135 err = convert_disk_buffer_to_posix_acl(x->value, x->value_len, 1136 value, value_len); 1137 return err; 1138 } else { 1139 err = ext2fs_get_mem(x->value_len, &val); 1140 if (err) 1141 return err; 1142 memcpy(val, x->value, x->value_len); 1143 *value = val; 1144 *value_len = x->value_len; 1145 return 0; 1146 } 1147 } 1148 1149 return EXT2_ET_EA_KEY_NOT_FOUND; 1150 } 1151 1152 errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino, 1153 size_t *size) 1154 { 1155 struct ext2_ext_attr_entry *entry; 1156 struct ext2_inode_large *inode; 1157 __u32 ea_inode_magic; 1158 unsigned int minoff; 1159 char *start; 1160 size_t i; 1161 errcode_t err; 1162 1163 i = EXT2_INODE_SIZE(fs->super); 1164 if (i < sizeof(*inode)) 1165 i = sizeof(*inode); 1166 err = ext2fs_get_memzero(i, &inode); 1167 if (err) 1168 return err; 1169 1170 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)inode, 1171 EXT2_INODE_SIZE(fs->super)); 1172 if (err) 1173 goto out; 1174 1175 /* Does the inode have size for EA? */ 1176 if (EXT2_INODE_SIZE(fs->super) <= EXT2_GOOD_OLD_INODE_SIZE + 1177 inode->i_extra_isize + 1178 sizeof(__u32)) { 1179 err = EXT2_ET_INLINE_DATA_NO_SPACE; 1180 goto out; 1181 } 1182 1183 minoff = EXT2_INODE_SIZE(fs->super) - sizeof(*inode) - sizeof(__u32); 1184 memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1185 inode->i_extra_isize, sizeof(__u32)); 1186 if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) { 1187 /* has xattrs. calculate the size */ 1188 start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1189 inode->i_extra_isize + sizeof(__u32); 1190 entry = (struct ext2_ext_attr_entry *) start; 1191 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { 1192 if (!entry->e_value_inum && entry->e_value_size) { 1193 unsigned int offs = entry->e_value_offs; 1194 if (offs < minoff) 1195 minoff = offs; 1196 } 1197 entry = EXT2_EXT_ATTR_NEXT(entry); 1198 } 1199 *size = minoff - ((char *)entry - (char *)start) - sizeof(__u32); 1200 } else { 1201 /* no xattr. return a maximum size */ 1202 *size = EXT2_EXT_ATTR_SIZE(minoff - 1203 EXT2_EXT_ATTR_LEN(strlen("data")) - 1204 EXT2_EXT_ATTR_ROUND - sizeof(__u32)); 1205 } 1206 1207 out: 1208 ext2fs_free_mem(&inode); 1209 return err; 1210 } 1211 1212 static errcode_t xattr_create_ea_inode(ext2_filsys fs, const void *value, 1213 size_t value_len, ext2_ino_t *ea_ino) 1214 { 1215 struct ext2_inode inode; 1216 ext2_ino_t ino; 1217 ext2_file_t file; 1218 __u32 hash; 1219 errcode_t ret; 1220 1221 ret = ext2fs_new_inode(fs, 0, 0, 0, &ino); 1222 if (ret) 1223 return ret; 1224 1225 memset(&inode, 0, sizeof(inode)); 1226 inode.i_flags |= EXT4_EA_INODE_FL; 1227 if (ext2fs_has_feature_extents(fs->super)) 1228 inode.i_flags |= EXT4_EXTENTS_FL; 1229 inode.i_size = 0; 1230 inode.i_mode = LINUX_S_IFREG | 0600; 1231 inode.i_links_count = 1; 1232 ret = ext2fs_write_new_inode(fs, ino, &inode); 1233 if (ret) 1234 return ret; 1235 /* 1236 * ref_count and hash utilize inode's i_*time fields. 1237 * ext2fs_write_new_inode() call above initializes these fields with 1238 * current time. That's why ref count and hash updates are done 1239 * separately below. 1240 */ 1241 ext2fs_set_ea_inode_ref(&inode, 1); 1242 hash = ext2fs_crc32c_le(fs->csum_seed, value, value_len); 1243 ext2fs_set_ea_inode_hash(&inode, hash); 1244 1245 ret = ext2fs_write_inode(fs, ino, &inode); 1246 if (ret) 1247 return ret; 1248 1249 ret = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file); 1250 if (ret) 1251 return ret; 1252 ret = ext2fs_file_write(file, value, value_len, NULL); 1253 ext2fs_file_close(file); 1254 if (ret) 1255 return ret; 1256 1257 ext2fs_inode_alloc_stats2(fs, ino, 1 /* inuse */, 0 /* isdir */); 1258 1259 *ea_ino = ino; 1260 return 0; 1261 } 1262 1263 static errcode_t xattr_inode_dec_ref(ext2_filsys fs, ext2_ino_t ino) 1264 { 1265 struct ext2_inode_large inode; 1266 __u64 ref_count; 1267 errcode_t ret; 1268 1269 ret = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, 1270 sizeof(inode)); 1271 if (ret) 1272 goto out; 1273 1274 ref_count = ext2fs_get_ea_inode_ref(EXT2_INODE(&inode)); 1275 ref_count--; 1276 ext2fs_set_ea_inode_ref(EXT2_INODE(&inode), ref_count); 1277 1278 if (ref_count) 1279 goto write_out; 1280 1281 inode.i_links_count = 0; 1282 inode.i_dtime = fs->now ? fs->now : time(0); 1283 1284 ret = ext2fs_free_ext_attr(fs, ino, &inode); 1285 if (ret) 1286 goto write_out; 1287 1288 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) { 1289 ret = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL, 1290 0, ~0ULL); 1291 if (ret) 1292 goto out; 1293 } 1294 1295 ext2fs_inode_alloc_stats2(fs, ino, -1 /* inuse */, 0 /* is_dir */); 1296 1297 write_out: 1298 ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, 1299 sizeof(inode)); 1300 out: 1301 return ret; 1302 } 1303 1304 static errcode_t xattr_update_entry(ext2_filsys fs, struct ext2_xattr *x, 1305 const char *name, const void *value, 1306 size_t value_len, int in_inode) 1307 { 1308 ext2_ino_t ea_ino = 0; 1309 void *new_value = NULL; 1310 char *new_name = NULL; 1311 int name_len; 1312 errcode_t ret; 1313 1314 if (!x->name) { 1315 name_len = strlen(name); 1316 ret = ext2fs_get_mem(name_len + 1, &new_name); 1317 if (ret) 1318 goto fail; 1319 memcpy(new_name, name, name_len + 1); 1320 } 1321 1322 ret = ext2fs_get_mem(value_len, &new_value); 1323 if (ret) 1324 goto fail; 1325 memcpy(new_value, value, value_len); 1326 1327 if (in_inode) { 1328 ret = xattr_create_ea_inode(fs, value, value_len, &ea_ino); 1329 if (ret) 1330 goto fail; 1331 } 1332 1333 if (x->ea_ino) { 1334 ret = xattr_inode_dec_ref(fs, x->ea_ino); 1335 if (ret) 1336 goto fail; 1337 } 1338 1339 if (!x->name) 1340 x->name = new_name; 1341 1342 if (x->value) 1343 ext2fs_free_mem(&x->value); 1344 x->value = new_value; 1345 x->value_len = value_len; 1346 x->ea_ino = ea_ino; 1347 return 0; 1348 fail: 1349 if (new_name) 1350 ext2fs_free_mem(&new_name); 1351 if (new_value) 1352 ext2fs_free_mem(&new_value); 1353 if (ea_ino) 1354 xattr_inode_dec_ref(fs, ea_ino); 1355 return ret; 1356 } 1357 1358 static int xattr_find_position(struct ext2_xattr *attrs, int count, 1359 const char *name) 1360 { 1361 struct ext2_xattr *x; 1362 int i; 1363 const char *shortname, *x_shortname; 1364 int name_idx, x_name_idx; 1365 int shortname_len, x_shortname_len; 1366 1367 find_ea_index(name, &shortname, &name_idx); 1368 shortname_len = strlen(shortname); 1369 1370 for (i = 0, x = attrs; i < count; i++, x++) { 1371 find_ea_index(x->name, &x_shortname, &x_name_idx); 1372 if (name_idx < x_name_idx) 1373 break; 1374 if (name_idx > x_name_idx) 1375 continue; 1376 1377 x_shortname_len = strlen(x_shortname); 1378 if (shortname_len < x_shortname_len) 1379 break; 1380 if (shortname_len > x_shortname_len) 1381 continue; 1382 1383 if (memcmp(shortname, x_shortname, shortname_len) <= 0) 1384 break; 1385 } 1386 return i; 1387 } 1388 1389 static errcode_t xattr_array_update(struct ext2_xattr_handle *h, 1390 const char *name, 1391 const void *value, size_t value_len, 1392 int ibody_free, int block_free, 1393 int old_idx, int in_inode) 1394 { 1395 struct ext2_xattr tmp; 1396 int add_to_ibody; 1397 int needed; 1398 int name_len, name_idx; 1399 const char *shortname; 1400 int new_idx; 1401 int ret; 1402 1403 find_ea_index(name, &shortname, &name_idx); 1404 name_len = strlen(shortname); 1405 1406 needed = EXT2_EXT_ATTR_LEN(name_len); 1407 if (!in_inode) 1408 needed += EXT2_EXT_ATTR_SIZE(value_len); 1409 1410 if (old_idx >= 0 && old_idx < h->ibody_count) { 1411 ibody_free += EXT2_EXT_ATTR_LEN(name_len); 1412 if (!h->attrs[old_idx].ea_ino) 1413 ibody_free += EXT2_EXT_ATTR_SIZE( 1414 h->attrs[old_idx].value_len); 1415 } 1416 1417 if (needed <= ibody_free) { 1418 if (old_idx < 0) { 1419 new_idx = h->ibody_count; 1420 add_to_ibody = 1; 1421 goto add_new; 1422 } 1423 1424 /* Update the existing entry. */ 1425 ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name, 1426 value, value_len, in_inode); 1427 if (ret) 1428 return ret; 1429 if (h->ibody_count <= old_idx) { 1430 /* Move entry from block to the end of ibody. */ 1431 tmp = h->attrs[old_idx]; 1432 memmove(h->attrs + h->ibody_count + 1, 1433 h->attrs + h->ibody_count, 1434 (old_idx - h->ibody_count) * sizeof(*h->attrs)); 1435 h->attrs[h->ibody_count] = tmp; 1436 h->ibody_count++; 1437 } 1438 return 0; 1439 } 1440 1441 if (h->ibody_count <= old_idx) { 1442 block_free += EXT2_EXT_ATTR_LEN(name_len); 1443 if (!h->attrs[old_idx].ea_ino) 1444 block_free += 1445 EXT2_EXT_ATTR_SIZE(h->attrs[old_idx].value_len); 1446 } 1447 1448 if (needed > block_free) 1449 return EXT2_ET_EA_NO_SPACE; 1450 1451 if (old_idx >= 0) { 1452 /* Update the existing entry. */ 1453 ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name, 1454 value, value_len, in_inode); 1455 if (ret) 1456 return ret; 1457 if (old_idx < h->ibody_count) { 1458 /* 1459 * Move entry from ibody to the block. Note that 1460 * entries in the block are sorted. 1461 */ 1462 new_idx = xattr_find_position(h->attrs + h->ibody_count, 1463 h->count - h->ibody_count, name); 1464 new_idx += h->ibody_count - 1; 1465 tmp = h->attrs[old_idx]; 1466 memmove(h->attrs + old_idx, h->attrs + old_idx + 1, 1467 (new_idx - old_idx) * sizeof(*h->attrs)); 1468 h->attrs[new_idx] = tmp; 1469 h->ibody_count--; 1470 } 1471 return 0; 1472 } 1473 1474 new_idx = xattr_find_position(h->attrs + h->ibody_count, 1475 h->count - h->ibody_count, name); 1476 new_idx += h->ibody_count; 1477 add_to_ibody = 0; 1478 1479 add_new: 1480 if (h->count == h->capacity) { 1481 ret = ext2fs_xattrs_expand(h, 4); 1482 if (ret) 1483 return ret; 1484 } 1485 1486 ret = xattr_update_entry(h->fs, &h->attrs[h->count], name, value, 1487 value_len, in_inode); 1488 if (ret) 1489 return ret; 1490 1491 tmp = h->attrs[h->count]; 1492 memmove(h->attrs + new_idx + 1, h->attrs + new_idx, 1493 (h->count - new_idx)*sizeof(*h->attrs)); 1494 h->attrs[new_idx] = tmp; 1495 if (add_to_ibody) 1496 h->ibody_count++; 1497 h->count++; 1498 return 0; 1499 } 1500 1501 static int space_used(struct ext2_xattr *attrs, int count) 1502 { 1503 int total = 0; 1504 struct ext2_xattr *x; 1505 const char *shortname; 1506 int i, len, name_idx; 1507 1508 for (i = 0, x = attrs; i < count; i++, x++) { 1509 find_ea_index(x->name, &shortname, &name_idx); 1510 len = strlen(shortname); 1511 total += EXT2_EXT_ATTR_LEN(len); 1512 if (!x->ea_ino) 1513 total += EXT2_EXT_ATTR_SIZE(x->value_len); 1514 } 1515 return total; 1516 } 1517 1518 /* 1519 * The minimum size of EA value when you start storing it in an external inode 1520 * size of block - size of header - size of 1 entry - 4 null bytes 1521 */ 1522 #define EXT4_XATTR_MIN_LARGE_EA_SIZE(b) \ 1523 ((b) - EXT2_EXT_ATTR_LEN(3) - sizeof(struct ext2_ext_attr_header) - 4) 1524 1525 errcode_t ext2fs_xattr_set(struct ext2_xattr_handle *h, 1526 const char *name, 1527 const void *value, 1528 size_t value_len) 1529 { 1530 ext2_filsys fs = h->fs; 1531 const int inode_size = EXT2_INODE_SIZE(fs->super); 1532 struct ext2_inode_large *inode = NULL; 1533 struct ext2_xattr *x; 1534 char *new_value; 1535 int ibody_free, block_free; 1536 int in_inode = 0; 1537 int old_idx = -1; 1538 int extra_isize; 1539 errcode_t ret; 1540 1541 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1542 1543 ret = ext2fs_get_mem(value_len, &new_value); 1544 if (ret) 1545 return ret; 1546 if (!(h->flags & XATTR_HANDLE_FLAG_RAW) && 1547 ((strcmp(name, "system.posix_acl_default") == 0) || 1548 (strcmp(name, "system.posix_acl_access") == 0))) { 1549 ret = convert_posix_acl_to_disk_buffer(value, value_len, 1550 new_value, &value_len); 1551 if (ret) 1552 goto out; 1553 } else 1554 memcpy(new_value, value, value_len); 1555 1556 /* Imitate kernel behavior by skipping update if value is the same. */ 1557 for (x = h->attrs; x < h->attrs + h->count; x++) { 1558 if (!strcmp(x->name, name)) { 1559 if (!x->ea_ino && x->value_len == value_len && 1560 !memcmp(x->value, new_value, value_len)) { 1561 ret = 0; 1562 goto out; 1563 } 1564 old_idx = x - h->attrs; 1565 break; 1566 } 1567 } 1568 1569 ret = ext2fs_get_memzero(inode_size, &inode); 1570 if (ret) 1571 goto out; 1572 ret = ext2fs_read_inode_full(fs, h->ino, 1573 (struct ext2_inode *)inode, 1574 inode_size); 1575 if (ret) 1576 goto out; 1577 if (inode_size > EXT2_GOOD_OLD_INODE_SIZE) { 1578 extra_isize = inode->i_extra_isize; 1579 if (extra_isize == 0) { 1580 extra_isize = fs->super->s_want_extra_isize; 1581 if (extra_isize == 0) 1582 extra_isize = sizeof(__u32); 1583 } 1584 ibody_free = inode_size - EXT2_GOOD_OLD_INODE_SIZE; 1585 ibody_free -= extra_isize; 1586 /* Extended attribute magic and final null entry. */ 1587 ibody_free -= sizeof(__u32) * 2; 1588 ibody_free -= space_used(h->attrs, h->ibody_count); 1589 } else 1590 ibody_free = 0; 1591 1592 /* Inline data can only go to ibody. */ 1593 if (strcmp(name, "system.data") == 0) { 1594 if (h->ibody_count <= old_idx) { 1595 ret = EXT2_ET_FILESYSTEM_CORRUPTED; 1596 goto out; 1597 } 1598 ret = xattr_array_update(h, name, value, value_len, ibody_free, 1599 0 /* block_free */, old_idx, 1600 0 /* in_inode */); 1601 if (ret) 1602 goto out; 1603 goto write_out; 1604 } 1605 1606 block_free = fs->blocksize; 1607 block_free -= sizeof(struct ext2_ext_attr_header); 1608 /* Final null entry. */ 1609 block_free -= sizeof(__u32); 1610 block_free -= space_used(h->attrs + h->ibody_count, 1611 h->count - h->ibody_count); 1612 1613 if (ext2fs_has_feature_ea_inode(fs->super) && 1614 value_len > EXT4_XATTR_MIN_LARGE_EA_SIZE(fs->blocksize)) 1615 in_inode = 1; 1616 1617 ret = xattr_array_update(h, name, value, value_len, ibody_free, 1618 block_free, old_idx, in_inode); 1619 if (ret == EXT2_ET_EA_NO_SPACE && !in_inode && 1620 ext2fs_has_feature_ea_inode(fs->super)) 1621 ret = xattr_array_update(h, name, value, value_len, ibody_free, 1622 block_free, old_idx, 1 /* in_inode */); 1623 if (ret) 1624 goto out; 1625 1626 write_out: 1627 ret = ext2fs_xattrs_write(h); 1628 out: 1629 if (inode) 1630 ext2fs_free_mem(&inode); 1631 ext2fs_free_mem(&new_value); 1632 return ret; 1633 } 1634 1635 errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle, 1636 const char *key) 1637 { 1638 struct ext2_xattr *x; 1639 struct ext2_xattr *end = handle->attrs + handle->count; 1640 1641 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1642 for (x = handle->attrs; x < end; x++) { 1643 if (strcmp(x->name, key) == 0) { 1644 ext2fs_free_mem(&x->name); 1645 ext2fs_free_mem(&x->value); 1646 if (x->ea_ino) 1647 xattr_inode_dec_ref(handle->fs, x->ea_ino); 1648 memmove(x, x + 1, (end - x - 1)*sizeof(*x)); 1649 memset(end - 1, 0, sizeof(*end)); 1650 if (x < handle->attrs + handle->ibody_count) 1651 handle->ibody_count--; 1652 handle->count--; 1653 return ext2fs_xattrs_write(handle); 1654 } 1655 } 1656 1657 /* no key found, success! */ 1658 return 0; 1659 } 1660 1661 errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino, 1662 struct ext2_xattr_handle **handle) 1663 { 1664 struct ext2_xattr_handle *h; 1665 errcode_t err; 1666 1667 if (!ext2fs_has_feature_xattr(fs->super) && 1668 !ext2fs_has_feature_inline_data(fs->super)) 1669 return EXT2_ET_MISSING_EA_FEATURE; 1670 1671 err = ext2fs_get_memzero(sizeof(*h), &h); 1672 if (err) 1673 return err; 1674 1675 h->magic = EXT2_ET_MAGIC_EA_HANDLE; 1676 h->capacity = 4; 1677 err = ext2fs_get_arrayzero(h->capacity, sizeof(struct ext2_xattr), 1678 &h->attrs); 1679 if (err) { 1680 ext2fs_free_mem(&h); 1681 return err; 1682 } 1683 h->count = 0; 1684 h->ino = ino; 1685 h->fs = fs; 1686 *handle = h; 1687 return 0; 1688 } 1689 1690 errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle) 1691 { 1692 struct ext2_xattr_handle *h = *handle; 1693 1694 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1695 xattrs_free_keys(h); 1696 ext2fs_free_mem(&h->attrs); 1697 ext2fs_free_mem(handle); 1698 return 0; 1699 } 1700 1701 errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count) 1702 { 1703 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1704 *count = handle->count; 1705 return 0; 1706 } 1707 1708 errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle, 1709 unsigned int *new_flags, unsigned int *old_flags) 1710 { 1711 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1712 if (old_flags) 1713 *old_flags = handle->flags; 1714 if (new_flags) 1715 handle->flags = *new_flags; 1716 return 0; 1717 } 1718