1 /* 2 * ext_attr.c --- extended attribute blocks 3 * 4 * Copyright (C) 2001 Andreas Gruenbacher, <a.gruenbacher@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 int name_index; 297 char *name; 298 char *short_name; 299 void *value; 300 unsigned int value_len; 301 ext2_ino_t ea_ino; 302 }; 303 304 struct ext2_xattr_handle { 305 errcode_t magic; 306 ext2_filsys fs; 307 struct ext2_xattr *attrs; 308 int capacity; 309 int count; 310 int ibody_count; 311 ext2_ino_t ino; 312 unsigned int flags; 313 }; 314 315 static errcode_t ext2fs_xattrs_expand(struct ext2_xattr_handle *h, 316 unsigned int expandby) 317 { 318 struct ext2_xattr *new_attrs; 319 errcode_t err; 320 321 err = ext2fs_get_arrayzero(h->capacity + expandby, 322 sizeof(struct ext2_xattr), &new_attrs); 323 if (err) 324 return err; 325 326 memcpy(new_attrs, h->attrs, h->capacity * sizeof(struct ext2_xattr)); 327 ext2fs_free_mem(&h->attrs); 328 h->capacity += expandby; 329 h->attrs = new_attrs; 330 331 return 0; 332 } 333 334 struct ea_name_index { 335 int index; 336 const char *name; 337 }; 338 339 /* Keep these names sorted in order of decreasing specificity. */ 340 static struct ea_name_index ea_names[] = { 341 {10, "gnu."}, 342 {3, "system.posix_acl_default"}, 343 {2, "system.posix_acl_access"}, 344 {8, "system.richacl"}, 345 {6, "security."}, 346 {4, "trusted."}, 347 {7, "system."}, 348 {1, "user."}, 349 {0, NULL}, 350 }; 351 352 static const char *find_ea_prefix(int index) 353 { 354 struct ea_name_index *e; 355 356 for (e = ea_names; e->name; e++) 357 if (e->index == index) 358 return e->name; 359 360 return NULL; 361 } 362 363 static int find_ea_index(const char *fullname, const char **name, int *index) 364 { 365 struct ea_name_index *e; 366 367 for (e = ea_names; e->name; e++) { 368 if (strncmp(fullname, e->name, strlen(e->name)) == 0) { 369 *name = fullname + strlen(e->name); 370 *index = e->index; 371 return 1; 372 } 373 } 374 return 0; 375 } 376 377 errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino, 378 struct ext2_inode_large *inode) 379 { 380 struct ext2_ext_attr_header *header; 381 void *block_buf = NULL; 382 blk64_t blk; 383 errcode_t err; 384 struct ext2_inode_large i; 385 386 /* Read inode? */ 387 if (inode == NULL) { 388 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&i, 389 sizeof(struct ext2_inode_large)); 390 if (err) 391 return err; 392 inode = &i; 393 } 394 395 /* Do we already have an EA block? */ 396 blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); 397 if (blk == 0) 398 return 0; 399 400 /* Find block, zero it, write back */ 401 if ((blk < fs->super->s_first_data_block) || 402 (blk >= ext2fs_blocks_count(fs->super))) { 403 err = EXT2_ET_BAD_EA_BLOCK_NUM; 404 goto out; 405 } 406 407 err = ext2fs_get_mem(fs->blocksize, &block_buf); 408 if (err) 409 goto out; 410 411 err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino); 412 if (err) 413 goto out2; 414 415 /* We only know how to deal with v2 EA blocks */ 416 header = (struct ext2_ext_attr_header *) block_buf; 417 if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { 418 err = EXT2_ET_BAD_EA_HEADER; 419 goto out2; 420 } 421 422 header->h_refcount--; 423 err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino); 424 if (err) 425 goto out2; 426 427 /* Erase link to block */ 428 ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, 0); 429 if (header->h_refcount == 0) 430 ext2fs_block_alloc_stats2(fs, blk, -1); 431 err = ext2fs_iblk_sub_blocks(fs, (struct ext2_inode *)inode, 1); 432 if (err) 433 goto out2; 434 435 /* Write inode? */ 436 if (inode == &i) { 437 err = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&i, 438 sizeof(struct ext2_inode_large)); 439 if (err) 440 goto out2; 441 } 442 443 out2: 444 ext2fs_free_mem(&block_buf); 445 out: 446 return err; 447 } 448 449 static errcode_t prep_ea_block_for_write(ext2_filsys fs, ext2_ino_t ino, 450 struct ext2_inode_large *inode) 451 { 452 struct ext2_ext_attr_header *header; 453 void *block_buf = NULL; 454 blk64_t blk, goal; 455 errcode_t err; 456 457 /* Do we already have an EA block? */ 458 blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); 459 if (blk != 0) { 460 if ((blk < fs->super->s_first_data_block) || 461 (blk >= ext2fs_blocks_count(fs->super))) { 462 err = EXT2_ET_BAD_EA_BLOCK_NUM; 463 goto out; 464 } 465 466 err = ext2fs_get_mem(fs->blocksize, &block_buf); 467 if (err) 468 goto out; 469 470 err = ext2fs_read_ext_attr3(fs, blk, block_buf, ino); 471 if (err) 472 goto out2; 473 474 /* We only know how to deal with v2 EA blocks */ 475 header = (struct ext2_ext_attr_header *) block_buf; 476 if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { 477 err = EXT2_ET_BAD_EA_HEADER; 478 goto out2; 479 } 480 481 /* Single-user block. We're done here. */ 482 if (header->h_refcount == 1) 483 goto out2; 484 485 /* We need to CoW the block. */ 486 header->h_refcount--; 487 err = ext2fs_write_ext_attr3(fs, blk, block_buf, ino); 488 if (err) 489 goto out2; 490 } else { 491 /* No block, we must increment i_blocks */ 492 err = ext2fs_iblk_add_blocks(fs, (struct ext2_inode *)inode, 493 1); 494 if (err) 495 goto out; 496 } 497 498 /* Allocate a block */ 499 goal = ext2fs_find_inode_goal(fs, ino, (struct ext2_inode *)inode, 0); 500 err = ext2fs_alloc_block2(fs, goal, NULL, &blk); 501 if (err) 502 goto out2; 503 ext2fs_file_acl_block_set(fs, (struct ext2_inode *)inode, blk); 504 out2: 505 if (block_buf) 506 ext2fs_free_mem(&block_buf); 507 out: 508 return err; 509 } 510 511 512 static inline int 513 posix_acl_xattr_count(size_t size) 514 { 515 if (size < sizeof(posix_acl_xattr_header)) 516 return -1; 517 size -= sizeof(posix_acl_xattr_header); 518 if (size % sizeof(posix_acl_xattr_entry)) 519 return -1; 520 return size / sizeof(posix_acl_xattr_entry); 521 } 522 523 /* 524 * The lgetxattr function returns data formatted in the POSIX extended 525 * attribute format. The on-disk format uses a more compact encoding. 526 * See the ext4_acl_to_disk in fs/ext4/acl.c. 527 */ 528 static errcode_t convert_posix_acl_to_disk_buffer(const void *value, size_t size, 529 void *out_buf, size_t *size_out) 530 { 531 const posix_acl_xattr_header *header = 532 (const posix_acl_xattr_header*) value; 533 const posix_acl_xattr_entry *end, *entry = 534 (const posix_acl_xattr_entry *)(header+1); 535 ext4_acl_header *ext_acl; 536 size_t s; 537 char *e; 538 539 int count; 540 541 if (!value) 542 return EINVAL; 543 if (size < sizeof(posix_acl_xattr_header)) 544 return ENOMEM; 545 if (header->a_version != ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION)) 546 return EINVAL; 547 548 count = posix_acl_xattr_count(size); 549 ext_acl = out_buf; 550 ext_acl->a_version = ext2fs_cpu_to_le32(EXT4_ACL_VERSION); 551 552 if (count <= 0) 553 return EINVAL; 554 555 e = (char *) out_buf + sizeof(ext4_acl_header); 556 s = sizeof(ext4_acl_header); 557 for (end = entry + count; entry != end;entry++) { 558 ext4_acl_entry *disk_entry = (ext4_acl_entry*) e; 559 disk_entry->e_tag = ext2fs_cpu_to_le16(entry->e_tag); 560 disk_entry->e_perm = ext2fs_cpu_to_le16(entry->e_perm); 561 562 switch(entry->e_tag) { 563 case ACL_USER_OBJ: 564 case ACL_GROUP_OBJ: 565 case ACL_MASK: 566 case ACL_OTHER: 567 e += sizeof(ext4_acl_entry_short); 568 s += sizeof(ext4_acl_entry_short); 569 break; 570 case ACL_USER: 571 case ACL_GROUP: 572 disk_entry->e_id = ext2fs_cpu_to_le32(entry->e_id); 573 e += sizeof(ext4_acl_entry); 574 s += sizeof(ext4_acl_entry); 575 break; 576 } 577 } 578 *size_out = s; 579 return 0; 580 } 581 582 static errcode_t convert_disk_buffer_to_posix_acl(const void *value, size_t size, 583 void **out_buf, size_t *size_out) 584 { 585 posix_acl_xattr_header *header; 586 posix_acl_xattr_entry *entry; 587 const ext4_acl_header *ext_acl = (const ext4_acl_header *) value; 588 errcode_t err; 589 const char *cp; 590 char *out; 591 592 if ((!value) || 593 (size < sizeof(ext4_acl_header)) || 594 (ext_acl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))) 595 return EINVAL; 596 597 err = ext2fs_get_mem(size * 2, &out); 598 if (err) 599 return err; 600 601 header = (posix_acl_xattr_header *) out; 602 header->a_version = ext2fs_cpu_to_le32(POSIX_ACL_XATTR_VERSION); 603 entry = (posix_acl_xattr_entry *) (out + sizeof(posix_acl_xattr_header)); 604 605 cp = (const char *) value + sizeof(ext4_acl_header); 606 size -= sizeof(ext4_acl_header); 607 608 while (size > 0) { 609 const ext4_acl_entry *disk_entry = (const ext4_acl_entry *) cp; 610 611 entry->e_tag = ext2fs_le16_to_cpu(disk_entry->e_tag); 612 entry->e_perm = ext2fs_le16_to_cpu(disk_entry->e_perm); 613 614 switch(entry->e_tag) { 615 case ACL_USER_OBJ: 616 case ACL_GROUP_OBJ: 617 case ACL_MASK: 618 case ACL_OTHER: 619 entry->e_id = 0; 620 cp += sizeof(ext4_acl_entry_short); 621 size -= sizeof(ext4_acl_entry_short); 622 break; 623 case ACL_USER: 624 case ACL_GROUP: 625 entry->e_id = ext2fs_le32_to_cpu(disk_entry->e_id); 626 cp += sizeof(ext4_acl_entry); 627 size -= sizeof(ext4_acl_entry); 628 break; 629 default: 630 ext2fs_free_mem(&out); 631 return EINVAL; 632 } 633 entry++; 634 } 635 *out_buf = out; 636 *size_out = ((char *) entry - out); 637 return 0; 638 } 639 640 static errcode_t 641 write_xattrs_to_buffer(ext2_filsys fs, struct ext2_xattr *attrs, int count, 642 void *entries_start, unsigned int storage_size, 643 unsigned int value_offset_correction, int write_hash) 644 { 645 struct ext2_xattr *x; 646 struct ext2_ext_attr_entry *e = entries_start; 647 char *end = (char *) entries_start + storage_size; 648 unsigned int value_size; 649 errcode_t err; 650 651 memset(entries_start, 0, storage_size); 652 for (x = attrs; x < attrs + count; x++) { 653 value_size = ((x->value_len + EXT2_EXT_ATTR_PAD - 1) / 654 EXT2_EXT_ATTR_PAD) * EXT2_EXT_ATTR_PAD; 655 656 /* Fill out e appropriately */ 657 e->e_name_len = strlen(x->short_name); 658 e->e_name_index = x->name_index; 659 660 e->e_value_size = x->value_len; 661 e->e_value_inum = x->ea_ino; 662 663 /* Store name */ 664 memcpy((char *)e + sizeof(*e), x->short_name, e->e_name_len); 665 if (x->ea_ino) { 666 e->e_value_offs = 0; 667 } else { 668 end -= value_size; 669 e->e_value_offs = end - (char *) entries_start + 670 value_offset_correction; 671 memcpy(end, x->value, e->e_value_size); 672 } 673 674 if (write_hash || x->ea_ino) { 675 err = ext2fs_ext_attr_hash_entry2(fs, e, 676 x->ea_ino ? 0 : end, 677 &e->e_hash); 678 if (err) 679 return err; 680 } else 681 e->e_hash = 0; 682 683 e = EXT2_EXT_ATTR_NEXT(e); 684 *(__u32 *)e = 0; 685 } 686 return 0; 687 } 688 689 errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle) 690 { 691 ext2_filsys fs = handle->fs; 692 const unsigned int inode_size = EXT2_INODE_SIZE(fs->super); 693 struct ext2_inode_large *inode; 694 char *start, *block_buf = NULL; 695 struct ext2_ext_attr_header *header; 696 __u32 ea_inode_magic; 697 blk64_t blk; 698 unsigned int storage_size; 699 unsigned int i; 700 errcode_t err; 701 702 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 703 i = inode_size; 704 if (i < sizeof(*inode)) 705 i = sizeof(*inode); 706 err = ext2fs_get_memzero(i, &inode); 707 if (err) 708 return err; 709 710 err = ext2fs_read_inode_full(fs, handle->ino, EXT2_INODE(inode), 711 inode_size); 712 if (err) 713 goto out; 714 715 /* If extra_isize isn't set, we need to set it now */ 716 if (inode->i_extra_isize == 0 && 717 inode_size > EXT2_GOOD_OLD_INODE_SIZE) { 718 char *p = (char *)inode; 719 size_t extra = fs->super->s_want_extra_isize; 720 721 if (extra == 0) 722 extra = sizeof(__u32); 723 memset(p + EXT2_GOOD_OLD_INODE_SIZE, 0, extra); 724 inode->i_extra_isize = extra; 725 } 726 if (inode->i_extra_isize & 3) { 727 err = EXT2_ET_INODE_CORRUPTED; 728 goto out; 729 } 730 731 /* Does the inode have space for EA? */ 732 if (inode->i_extra_isize < sizeof(inode->i_extra_isize) || 733 inode_size <= EXT2_GOOD_OLD_INODE_SIZE + inode->i_extra_isize + 734 sizeof(__u32)) 735 goto write_ea_block; 736 737 /* Write the inode EA */ 738 ea_inode_magic = EXT2_EXT_ATTR_MAGIC; 739 memcpy(((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 740 inode->i_extra_isize, &ea_inode_magic, sizeof(__u32)); 741 storage_size = inode_size - EXT2_GOOD_OLD_INODE_SIZE - 742 inode->i_extra_isize - sizeof(__u32); 743 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 744 inode->i_extra_isize + sizeof(__u32); 745 746 err = write_xattrs_to_buffer(fs, handle->attrs, handle->ibody_count, 747 start, storage_size, 0, 0); 748 if (err) 749 goto out; 750 write_ea_block: 751 /* Are we done? */ 752 if (handle->ibody_count == handle->count && 753 !ext2fs_file_acl_block(fs, EXT2_INODE(inode))) 754 goto skip_ea_block; 755 756 /* Write the EA block */ 757 err = ext2fs_get_memzero(fs->blocksize, &block_buf); 758 if (err) 759 goto out; 760 761 storage_size = fs->blocksize - sizeof(struct ext2_ext_attr_header); 762 start = block_buf + sizeof(struct ext2_ext_attr_header); 763 764 err = write_xattrs_to_buffer(fs, handle->attrs + handle->ibody_count, 765 handle->count - handle->ibody_count, start, 766 storage_size, start - block_buf, 1); 767 if (err) 768 goto out2; 769 770 /* Write a header on the EA block */ 771 header = (struct ext2_ext_attr_header *) block_buf; 772 header->h_magic = EXT2_EXT_ATTR_MAGIC; 773 header->h_refcount = 1; 774 header->h_blocks = 1; 775 776 /* Get a new block for writing */ 777 err = prep_ea_block_for_write(fs, handle->ino, inode); 778 if (err) 779 goto out2; 780 781 /* Finally, write the new EA block */ 782 blk = ext2fs_file_acl_block(fs, EXT2_INODE(inode)); 783 err = ext2fs_write_ext_attr3(fs, blk, block_buf, handle->ino); 784 if (err) 785 goto out2; 786 787 skip_ea_block: 788 blk = ext2fs_file_acl_block(fs, (struct ext2_inode *)inode); 789 if (!block_buf && blk) { 790 /* xattrs shrunk, free the block */ 791 err = ext2fs_free_ext_attr(fs, handle->ino, inode); 792 if (err) 793 goto out; 794 } 795 796 /* Write the inode */ 797 err = ext2fs_write_inode_full(fs, handle->ino, EXT2_INODE(inode), 798 inode_size); 799 if (err) 800 goto out2; 801 802 out2: 803 ext2fs_free_mem(&block_buf); 804 out: 805 ext2fs_free_mem(&inode); 806 return err; 807 } 808 809 static errcode_t read_xattrs_from_buffer(struct ext2_xattr_handle *handle, 810 struct ext2_inode_large *inode, 811 struct ext2_ext_attr_entry *entries, 812 unsigned int storage_size, 813 char *value_start) 814 { 815 struct ext2_xattr *x; 816 struct ext2_ext_attr_entry *entry, *end; 817 const char *prefix; 818 unsigned int remain, prefix_len; 819 errcode_t err; 820 unsigned int values_size = storage_size + 821 ((char *)entries - value_start); 822 823 /* find the end */ 824 end = entries; 825 remain = storage_size; 826 while (remain >= sizeof(struct ext2_ext_attr_entry) && 827 !EXT2_EXT_IS_LAST_ENTRY(end)) { 828 829 /* header eats this space */ 830 remain -= sizeof(struct ext2_ext_attr_entry); 831 832 /* is attribute name valid? */ 833 if (EXT2_EXT_ATTR_SIZE(end->e_name_len) > remain) 834 return EXT2_ET_EA_BAD_NAME_LEN; 835 836 /* attribute len eats this space */ 837 remain -= EXT2_EXT_ATTR_SIZE(end->e_name_len); 838 end = EXT2_EXT_ATTR_NEXT(end); 839 } 840 841 entry = entries; 842 remain = storage_size; 843 while (remain >= sizeof(struct ext2_ext_attr_entry) && 844 !EXT2_EXT_IS_LAST_ENTRY(entry)) { 845 846 /* Allocate space for more attrs? */ 847 if (handle->count == handle->capacity) { 848 err = ext2fs_xattrs_expand(handle, 4); 849 if (err) 850 return err; 851 } 852 853 x = handle->attrs + handle->count; 854 855 /* header eats this space */ 856 remain -= sizeof(struct ext2_ext_attr_entry); 857 858 /* attribute len eats this space */ 859 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len); 860 861 /* Extract name */ 862 prefix = find_ea_prefix(entry->e_name_index); 863 prefix_len = (prefix ? strlen(prefix) : 0); 864 err = ext2fs_get_memzero(entry->e_name_len + prefix_len + 1, 865 &x->name); 866 if (err) 867 return err; 868 if (prefix) 869 memcpy(x->name, prefix, prefix_len); 870 if (entry->e_name_len) 871 memcpy(x->name + prefix_len, 872 (char *)entry + sizeof(*entry), 873 entry->e_name_len); 874 x->short_name = x->name + prefix_len; 875 x->name_index = entry->e_name_index; 876 877 /* Check & copy value */ 878 if (!ext2fs_has_feature_ea_inode(handle->fs->super) && 879 entry->e_value_inum != 0) 880 return EXT2_ET_BAD_EA_BLOCK_NUM; 881 882 if (entry->e_value_inum == 0) { 883 if (entry->e_value_size > remain) 884 return EXT2_ET_EA_BAD_VALUE_SIZE; 885 886 if (entry->e_value_offs + entry->e_value_size > values_size) 887 return EXT2_ET_EA_BAD_VALUE_OFFSET; 888 889 if (entry->e_value_size > 0 && 890 value_start + entry->e_value_offs < 891 (char *)end + sizeof(__u32)) 892 return EXT2_ET_EA_BAD_VALUE_OFFSET; 893 894 remain -= entry->e_value_size; 895 896 err = ext2fs_get_mem(entry->e_value_size, &x->value); 897 if (err) 898 return err; 899 memcpy(x->value, value_start + entry->e_value_offs, 900 entry->e_value_size); 901 } else { 902 struct ext2_inode *ea_inode; 903 ext2_file_t ea_file; 904 905 if (entry->e_value_offs != 0) 906 return EXT2_ET_EA_BAD_VALUE_OFFSET; 907 908 if (entry->e_value_size > (64 * 1024)) 909 return EXT2_ET_EA_BAD_VALUE_SIZE; 910 911 err = ext2fs_get_mem(entry->e_value_size, &x->value); 912 if (err) 913 return err; 914 915 err = ext2fs_file_open(handle->fs, entry->e_value_inum, 916 0, &ea_file); 917 if (err) 918 return err; 919 920 ea_inode = ext2fs_file_get_inode(ea_file); 921 if ((ea_inode->i_flags & EXT4_INLINE_DATA_FL) || 922 !(ea_inode->i_flags & EXT4_EA_INODE_FL) || 923 ea_inode->i_links_count == 0) 924 err = EXT2_ET_EA_INODE_CORRUPTED; 925 else if ((__u64) ext2fs_file_get_size(ea_file) != 926 entry->e_value_size) 927 err = EXT2_ET_EA_BAD_VALUE_SIZE; 928 else 929 err = ext2fs_file_read(ea_file, x->value, 930 entry->e_value_size, 0); 931 ext2fs_file_close(ea_file); 932 if (err) 933 return err; 934 } 935 936 x->ea_ino = entry->e_value_inum; 937 x->value_len = entry->e_value_size; 938 939 /* e_hash may be 0 in older inode's ea */ 940 if (entry->e_hash != 0) { 941 __u32 hash; 942 void *data = (entry->e_value_inum != 0) ? 943 0 : value_start + entry->e_value_offs; 944 945 err = ext2fs_ext_attr_hash_entry2(handle->fs, entry, 946 data, &hash); 947 if (err) 948 return err; 949 if (entry->e_hash != hash) { 950 struct ext2_inode child; 951 952 /* Check whether this is an old Lustre-style 953 * ea_inode reference. 954 */ 955 err = ext2fs_read_inode(handle->fs, 956 entry->e_value_inum, 957 &child); 958 if (err) 959 return err; 960 if (child.i_mtime != handle->ino || 961 child.i_generation != inode->i_generation) 962 return EXT2_ET_BAD_EA_HASH; 963 } 964 } 965 966 handle->count++; 967 entry = EXT2_EXT_ATTR_NEXT(entry); 968 } 969 970 return 0; 971 } 972 973 static void xattrs_free_keys(struct ext2_xattr_handle *h) 974 { 975 struct ext2_xattr *a = h->attrs; 976 int i; 977 978 for (i = 0; i < h->capacity; i++) { 979 if (a[i].name) 980 ext2fs_free_mem(&a[i].name); 981 if (a[i].value) 982 ext2fs_free_mem(&a[i].value); 983 } 984 h->count = 0; 985 h->ibody_count = 0; 986 } 987 988 errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle) 989 { 990 struct ext2_inode_large *inode; 991 struct ext2_ext_attr_header *header; 992 __u32 ea_inode_magic; 993 unsigned int storage_size; 994 char *start, *block_buf = NULL; 995 blk64_t blk; 996 size_t i; 997 errcode_t err; 998 999 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1000 i = EXT2_INODE_SIZE(handle->fs->super); 1001 if (i < sizeof(*inode)) 1002 i = sizeof(*inode); 1003 err = ext2fs_get_memzero(i, &inode); 1004 if (err) 1005 return err; 1006 1007 err = ext2fs_read_inode_full(handle->fs, handle->ino, 1008 (struct ext2_inode *)inode, 1009 EXT2_INODE_SIZE(handle->fs->super)); 1010 if (err) 1011 goto out; 1012 1013 xattrs_free_keys(handle); 1014 1015 /* Does the inode have space for EA? */ 1016 if (inode->i_extra_isize < sizeof(inode->i_extra_isize) || 1017 EXT2_INODE_SIZE(handle->fs->super) <= EXT2_GOOD_OLD_INODE_SIZE + 1018 inode->i_extra_isize + 1019 sizeof(__u32)) 1020 goto read_ea_block; 1021 if (inode->i_extra_isize & 3) { 1022 err = EXT2_ET_INODE_CORRUPTED; 1023 goto out; 1024 } 1025 1026 /* Look for EA in the inode */ 1027 memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1028 inode->i_extra_isize, sizeof(__u32)); 1029 if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) { 1030 storage_size = EXT2_INODE_SIZE(handle->fs->super) - 1031 EXT2_GOOD_OLD_INODE_SIZE - inode->i_extra_isize - 1032 sizeof(__u32); 1033 start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1034 inode->i_extra_isize + sizeof(__u32); 1035 1036 err = read_xattrs_from_buffer(handle, inode, 1037 (struct ext2_ext_attr_entry *) start, 1038 storage_size, start); 1039 if (err) 1040 goto out; 1041 1042 handle->ibody_count = handle->count; 1043 } 1044 1045 read_ea_block: 1046 /* Look for EA in a separate EA block */ 1047 blk = ext2fs_file_acl_block(handle->fs, (struct ext2_inode *)inode); 1048 if (blk != 0) { 1049 if ((blk < handle->fs->super->s_first_data_block) || 1050 (blk >= ext2fs_blocks_count(handle->fs->super))) { 1051 err = EXT2_ET_BAD_EA_BLOCK_NUM; 1052 goto out; 1053 } 1054 1055 err = ext2fs_get_mem(handle->fs->blocksize, &block_buf); 1056 if (err) 1057 goto out; 1058 1059 err = ext2fs_read_ext_attr3(handle->fs, blk, block_buf, 1060 handle->ino); 1061 if (err) 1062 goto out3; 1063 1064 /* We only know how to deal with v2 EA blocks */ 1065 header = (struct ext2_ext_attr_header *) block_buf; 1066 if (header->h_magic != EXT2_EXT_ATTR_MAGIC) { 1067 err = EXT2_ET_BAD_EA_HEADER; 1068 goto out3; 1069 } 1070 1071 /* Read EAs */ 1072 storage_size = handle->fs->blocksize - 1073 sizeof(struct ext2_ext_attr_header); 1074 start = block_buf + sizeof(struct ext2_ext_attr_header); 1075 err = read_xattrs_from_buffer(handle, inode, 1076 (struct ext2_ext_attr_entry *) start, 1077 storage_size, block_buf); 1078 if (err) 1079 goto out3; 1080 1081 ext2fs_free_mem(&block_buf); 1082 } 1083 1084 ext2fs_free_mem(&block_buf); 1085 ext2fs_free_mem(&inode); 1086 return 0; 1087 1088 out3: 1089 ext2fs_free_mem(&block_buf); 1090 out: 1091 ext2fs_free_mem(&inode); 1092 return err; 1093 } 1094 1095 errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h, 1096 int (*func)(char *name, char *value, 1097 size_t value_len, void *data), 1098 void *data) 1099 { 1100 struct ext2_xattr *x; 1101 int dirty = 0; 1102 int ret; 1103 1104 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1105 for (x = h->attrs; x < h->attrs + h->count; x++) { 1106 ret = func(x->name, x->value, x->value_len, data); 1107 if (ret & XATTR_CHANGED) 1108 dirty = 1; 1109 if (ret & XATTR_ABORT) 1110 break; 1111 } 1112 1113 if (dirty) 1114 return ext2fs_xattrs_write(h); 1115 return 0; 1116 } 1117 1118 errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key, 1119 void **value, size_t *value_len) 1120 { 1121 struct ext2_xattr *x; 1122 char *val; 1123 errcode_t err; 1124 1125 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1126 for (x = h->attrs; x < h->attrs + h->count; x++) { 1127 if (strcmp(x->name, key)) 1128 continue; 1129 1130 if (!(h->flags & XATTR_HANDLE_FLAG_RAW) && 1131 ((strcmp(key, "system.posix_acl_default") == 0) || 1132 (strcmp(key, "system.posix_acl_access") == 0))) { 1133 err = convert_disk_buffer_to_posix_acl(x->value, x->value_len, 1134 value, value_len); 1135 return err; 1136 } else { 1137 err = ext2fs_get_mem(x->value_len, &val); 1138 if (err) 1139 return err; 1140 memcpy(val, x->value, x->value_len); 1141 *value = val; 1142 *value_len = x->value_len; 1143 return 0; 1144 } 1145 } 1146 1147 return EXT2_ET_EA_KEY_NOT_FOUND; 1148 } 1149 1150 errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino, 1151 size_t *size) 1152 { 1153 struct ext2_ext_attr_entry *entry; 1154 struct ext2_inode_large *inode; 1155 __u32 ea_inode_magic; 1156 unsigned int minoff; 1157 char *start; 1158 size_t i; 1159 errcode_t err; 1160 1161 i = EXT2_INODE_SIZE(fs->super); 1162 if (i < sizeof(*inode)) 1163 i = sizeof(*inode); 1164 err = ext2fs_get_memzero(i, &inode); 1165 if (err) 1166 return err; 1167 1168 err = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)inode, 1169 EXT2_INODE_SIZE(fs->super)); 1170 if (err) 1171 goto out; 1172 1173 /* Does the inode have size for EA? */ 1174 if (EXT2_INODE_SIZE(fs->super) <= EXT2_GOOD_OLD_INODE_SIZE + 1175 inode->i_extra_isize + 1176 sizeof(__u32)) { 1177 err = EXT2_ET_INLINE_DATA_NO_SPACE; 1178 goto out; 1179 } 1180 1181 minoff = EXT2_INODE_SIZE(fs->super) - sizeof(*inode) - sizeof(__u32); 1182 memcpy(&ea_inode_magic, ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1183 inode->i_extra_isize, sizeof(__u32)); 1184 if (ea_inode_magic == EXT2_EXT_ATTR_MAGIC) { 1185 /* has xattrs. calculate the size */ 1186 start= ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE + 1187 inode->i_extra_isize + sizeof(__u32); 1188 entry = (struct ext2_ext_attr_entry *) start; 1189 while (!EXT2_EXT_IS_LAST_ENTRY(entry)) { 1190 if (!entry->e_value_inum && entry->e_value_size) { 1191 unsigned int offs = entry->e_value_offs; 1192 if (offs < minoff) 1193 minoff = offs; 1194 } 1195 entry = EXT2_EXT_ATTR_NEXT(entry); 1196 } 1197 *size = minoff - ((char *)entry - (char *)start) - sizeof(__u32); 1198 } else { 1199 /* no xattr. return a maximum size */ 1200 *size = EXT2_EXT_ATTR_SIZE(minoff - 1201 EXT2_EXT_ATTR_LEN(strlen("data")) - 1202 EXT2_EXT_ATTR_ROUND - sizeof(__u32)); 1203 } 1204 1205 out: 1206 ext2fs_free_mem(&inode); 1207 return err; 1208 } 1209 1210 static errcode_t xattr_create_ea_inode(ext2_filsys fs, const void *value, 1211 size_t value_len, ext2_ino_t *ea_ino) 1212 { 1213 struct ext2_inode inode; 1214 ext2_ino_t ino; 1215 ext2_file_t file; 1216 __u32 hash; 1217 errcode_t ret; 1218 1219 ret = ext2fs_new_inode(fs, 0, 0, 0, &ino); 1220 if (ret) 1221 return ret; 1222 1223 memset(&inode, 0, sizeof(inode)); 1224 inode.i_flags |= EXT4_EA_INODE_FL; 1225 if (ext2fs_has_feature_extents(fs->super)) 1226 inode.i_flags |= EXT4_EXTENTS_FL; 1227 inode.i_size = 0; 1228 inode.i_mode = LINUX_S_IFREG | 0600; 1229 inode.i_links_count = 1; 1230 ret = ext2fs_write_new_inode(fs, ino, &inode); 1231 if (ret) 1232 return ret; 1233 /* 1234 * ref_count and hash utilize inode's i_*time fields. 1235 * ext2fs_write_new_inode() call above initializes these fields with 1236 * current time. That's why ref count and hash updates are done 1237 * separately below. 1238 */ 1239 ext2fs_set_ea_inode_ref(&inode, 1); 1240 hash = ext2fs_crc32c_le(fs->csum_seed, value, value_len); 1241 ext2fs_set_ea_inode_hash(&inode, hash); 1242 1243 ret = ext2fs_write_inode(fs, ino, &inode); 1244 if (ret) 1245 return ret; 1246 1247 ret = ext2fs_file_open(fs, ino, EXT2_FILE_WRITE, &file); 1248 if (ret) 1249 return ret; 1250 ret = ext2fs_file_write(file, value, value_len, NULL); 1251 ext2fs_file_close(file); 1252 if (ret) 1253 return ret; 1254 1255 ext2fs_inode_alloc_stats2(fs, ino, 1 /* inuse */, 0 /* isdir */); 1256 1257 *ea_ino = ino; 1258 return 0; 1259 } 1260 1261 static errcode_t xattr_inode_dec_ref(ext2_filsys fs, ext2_ino_t ino) 1262 { 1263 struct ext2_inode_large inode; 1264 __u64 ref_count; 1265 errcode_t ret; 1266 1267 ret = ext2fs_read_inode_full(fs, ino, (struct ext2_inode *)&inode, 1268 sizeof(inode)); 1269 if (ret) 1270 goto out; 1271 1272 ref_count = ext2fs_get_ea_inode_ref(EXT2_INODE(&inode)); 1273 ref_count--; 1274 ext2fs_set_ea_inode_ref(EXT2_INODE(&inode), ref_count); 1275 1276 if (ref_count) 1277 goto write_out; 1278 1279 inode.i_links_count = 0; 1280 inode.i_dtime = fs->now ? fs->now : time(0); 1281 1282 ret = ext2fs_free_ext_attr(fs, ino, &inode); 1283 if (ret) 1284 goto write_out; 1285 1286 if (ext2fs_inode_has_valid_blocks2(fs, (struct ext2_inode *)&inode)) { 1287 ret = ext2fs_punch(fs, ino, (struct ext2_inode *)&inode, NULL, 1288 0, ~0ULL); 1289 if (ret) 1290 goto out; 1291 } 1292 1293 ext2fs_inode_alloc_stats2(fs, ino, -1 /* inuse */, 0 /* is_dir */); 1294 1295 write_out: 1296 ret = ext2fs_write_inode_full(fs, ino, (struct ext2_inode *)&inode, 1297 sizeof(inode)); 1298 out: 1299 return ret; 1300 } 1301 1302 static errcode_t xattr_update_entry(ext2_filsys fs, struct ext2_xattr *x, 1303 const char *name, const char *short_name, 1304 int index, const void *value, 1305 size_t value_len, int in_inode) 1306 { 1307 ext2_ino_t ea_ino = 0; 1308 void *new_value = NULL; 1309 char *new_name = NULL; 1310 int name_len; 1311 errcode_t ret; 1312 1313 if (!x->name) { 1314 name_len = strlen(name); 1315 ret = ext2fs_get_mem(name_len + 1, &new_name); 1316 if (ret) 1317 goto fail; 1318 memcpy(new_name, name, name_len + 1); 1319 } 1320 1321 ret = ext2fs_get_mem(value_len, &new_value); 1322 if (ret) 1323 goto fail; 1324 memcpy(new_value, value, value_len); 1325 1326 if (in_inode) { 1327 ret = xattr_create_ea_inode(fs, value, value_len, &ea_ino); 1328 if (ret) 1329 goto fail; 1330 } 1331 1332 if (x->ea_ino) { 1333 ret = xattr_inode_dec_ref(fs, x->ea_ino); 1334 if (ret) 1335 goto fail; 1336 } 1337 1338 if (!x->name) { 1339 x->name = new_name; 1340 x->short_name = new_name + (short_name - name); 1341 } 1342 x->name_index = index; 1343 1344 if (x->value) 1345 ext2fs_free_mem(&x->value); 1346 x->value = new_value; 1347 x->value_len = value_len; 1348 x->ea_ino = ea_ino; 1349 return 0; 1350 fail: 1351 if (new_name) 1352 ext2fs_free_mem(&new_name); 1353 if (new_value) 1354 ext2fs_free_mem(&new_value); 1355 if (ea_ino) 1356 xattr_inode_dec_ref(fs, ea_ino); 1357 return ret; 1358 } 1359 1360 static int xattr_find_position(struct ext2_xattr *attrs, int count, 1361 const char *shortname, int name_idx) 1362 { 1363 struct ext2_xattr *x; 1364 int i; 1365 int shortname_len, x_shortname_len; 1366 1367 shortname_len = strlen(shortname); 1368 1369 for (i = 0, x = attrs; i < count; i++, x++) { 1370 if (name_idx < x->name_index) 1371 break; 1372 if (name_idx > x->name_index) 1373 continue; 1374 1375 x_shortname_len = strlen(x->short_name); 1376 if (shortname_len < x_shortname_len) 1377 break; 1378 if (shortname_len > x_shortname_len) 1379 continue; 1380 1381 if (memcmp(shortname, x->short_name, shortname_len) <= 0) 1382 break; 1383 } 1384 return i; 1385 } 1386 1387 static errcode_t xattr_array_update(struct ext2_xattr_handle *h, 1388 const char *name, 1389 const void *value, size_t value_len, 1390 int ibody_free, int block_free, 1391 int old_idx, int in_inode) 1392 { 1393 struct ext2_xattr tmp; 1394 int add_to_ibody; 1395 int needed; 1396 int name_len, name_idx = 0; 1397 const char *shortname = name; 1398 int new_idx; 1399 int ret; 1400 1401 find_ea_index(name, &shortname, &name_idx); 1402 name_len = strlen(shortname); 1403 1404 needed = EXT2_EXT_ATTR_LEN(name_len); 1405 if (!in_inode) 1406 needed += EXT2_EXT_ATTR_SIZE(value_len); 1407 1408 if (old_idx >= 0 && old_idx < h->ibody_count) { 1409 ibody_free += EXT2_EXT_ATTR_LEN(name_len); 1410 if (!h->attrs[old_idx].ea_ino) 1411 ibody_free += EXT2_EXT_ATTR_SIZE( 1412 h->attrs[old_idx].value_len); 1413 } 1414 1415 if (needed <= ibody_free) { 1416 if (old_idx < 0) { 1417 new_idx = h->ibody_count; 1418 add_to_ibody = 1; 1419 goto add_new; 1420 } 1421 1422 /* Update the existing entry. */ 1423 ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name, 1424 shortname, name_idx, value, 1425 value_len, in_inode); 1426 if (ret) 1427 return ret; 1428 if (h->ibody_count <= old_idx) { 1429 /* Move entry from block to the end of ibody. */ 1430 tmp = h->attrs[old_idx]; 1431 memmove(h->attrs + h->ibody_count + 1, 1432 h->attrs + h->ibody_count, 1433 (old_idx - h->ibody_count) * sizeof(*h->attrs)); 1434 h->attrs[h->ibody_count] = tmp; 1435 h->ibody_count++; 1436 } 1437 return 0; 1438 } 1439 1440 if (h->ibody_count <= old_idx) { 1441 block_free += EXT2_EXT_ATTR_LEN(name_len); 1442 if (!h->attrs[old_idx].ea_ino) 1443 block_free += 1444 EXT2_EXT_ATTR_SIZE(h->attrs[old_idx].value_len); 1445 } 1446 1447 if (needed > block_free) 1448 return EXT2_ET_EA_NO_SPACE; 1449 1450 if (old_idx >= 0) { 1451 /* Update the existing entry. */ 1452 ret = xattr_update_entry(h->fs, &h->attrs[old_idx], name, 1453 shortname, name_idx, value, 1454 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, 1464 shortname, name_idx); 1465 new_idx += h->ibody_count - 1; 1466 tmp = h->attrs[old_idx]; 1467 memmove(h->attrs + old_idx, h->attrs + old_idx + 1, 1468 (new_idx - old_idx) * sizeof(*h->attrs)); 1469 h->attrs[new_idx] = tmp; 1470 h->ibody_count--; 1471 } 1472 return 0; 1473 } 1474 1475 new_idx = xattr_find_position(h->attrs + h->ibody_count, 1476 h->count - h->ibody_count, 1477 shortname, name_idx); 1478 new_idx += h->ibody_count; 1479 add_to_ibody = 0; 1480 1481 add_new: 1482 if (h->count == h->capacity) { 1483 ret = ext2fs_xattrs_expand(h, 4); 1484 if (ret) 1485 return ret; 1486 } 1487 1488 ret = xattr_update_entry(h->fs, &h->attrs[h->count], name, shortname, 1489 name_idx, value, value_len, in_inode); 1490 if (ret) 1491 return ret; 1492 1493 tmp = h->attrs[h->count]; 1494 memmove(h->attrs + new_idx + 1, h->attrs + new_idx, 1495 (h->count - new_idx)*sizeof(*h->attrs)); 1496 h->attrs[new_idx] = tmp; 1497 if (add_to_ibody) 1498 h->ibody_count++; 1499 h->count++; 1500 return 0; 1501 } 1502 1503 static int space_used(struct ext2_xattr *attrs, int count) 1504 { 1505 int total = 0; 1506 struct ext2_xattr *x; 1507 int i, len; 1508 1509 for (i = 0, x = attrs; i < count; i++, x++) { 1510 len = strlen(x->short_name); 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 if (value_len) 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 (!value_len || 1561 !memcmp(x->value, new_value, value_len))) { 1562 ret = 0; 1563 goto out; 1564 } 1565 old_idx = x - h->attrs; 1566 break; 1567 } 1568 } 1569 1570 ret = ext2fs_get_memzero(inode_size, &inode); 1571 if (ret) 1572 goto out; 1573 ret = ext2fs_read_inode_full(fs, h->ino, 1574 (struct ext2_inode *)inode, 1575 inode_size); 1576 if (ret) 1577 goto out; 1578 if (inode_size > EXT2_GOOD_OLD_INODE_SIZE) { 1579 extra_isize = inode->i_extra_isize; 1580 if (extra_isize == 0) { 1581 extra_isize = fs->super->s_want_extra_isize; 1582 if (extra_isize == 0) 1583 extra_isize = sizeof(__u32); 1584 } 1585 ibody_free = inode_size - EXT2_GOOD_OLD_INODE_SIZE; 1586 ibody_free -= extra_isize; 1587 /* Extended attribute magic and final null entry. */ 1588 ibody_free -= sizeof(__u32) * 2; 1589 ibody_free -= space_used(h->attrs, h->ibody_count); 1590 } else 1591 ibody_free = 0; 1592 1593 /* Inline data can only go to ibody. */ 1594 if (strcmp(name, "system.data") == 0) { 1595 if (h->ibody_count <= old_idx) { 1596 ret = EXT2_ET_FILESYSTEM_CORRUPTED; 1597 goto out; 1598 } 1599 ret = xattr_array_update(h, name, new_value, value_len, 1600 ibody_free, 1601 0 /* block_free */, old_idx, 1602 0 /* in_inode */); 1603 if (ret) 1604 goto out; 1605 goto write_out; 1606 } 1607 1608 block_free = fs->blocksize; 1609 block_free -= sizeof(struct ext2_ext_attr_header); 1610 /* Final null entry. */ 1611 block_free -= sizeof(__u32); 1612 block_free -= space_used(h->attrs + h->ibody_count, 1613 h->count - h->ibody_count); 1614 1615 if (ext2fs_has_feature_ea_inode(fs->super) && 1616 value_len > EXT4_XATTR_MIN_LARGE_EA_SIZE(fs->blocksize)) 1617 in_inode = 1; 1618 1619 ret = xattr_array_update(h, name, new_value, value_len, ibody_free, 1620 block_free, old_idx, in_inode); 1621 if (ret == EXT2_ET_EA_NO_SPACE && !in_inode && 1622 ext2fs_has_feature_ea_inode(fs->super)) 1623 ret = xattr_array_update(h, name, new_value, value_len, 1624 ibody_free, block_free, old_idx, 1 /* in_inode */); 1625 if (ret) 1626 goto out; 1627 1628 write_out: 1629 ret = ext2fs_xattrs_write(h); 1630 out: 1631 if (inode) 1632 ext2fs_free_mem(&inode); 1633 ext2fs_free_mem(&new_value); 1634 return ret; 1635 } 1636 1637 errcode_t ext2fs_xattr_remove(struct ext2_xattr_handle *handle, 1638 const char *key) 1639 { 1640 struct ext2_xattr *x; 1641 struct ext2_xattr *end = handle->attrs + handle->count; 1642 1643 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1644 for (x = handle->attrs; x < end; x++) { 1645 if (strcmp(x->name, key) == 0) { 1646 ext2fs_free_mem(&x->name); 1647 ext2fs_free_mem(&x->value); 1648 if (x->ea_ino) 1649 xattr_inode_dec_ref(handle->fs, x->ea_ino); 1650 memmove(x, x + 1, (end - x - 1)*sizeof(*x)); 1651 memset(end - 1, 0, sizeof(*end)); 1652 if (x < handle->attrs + handle->ibody_count) 1653 handle->ibody_count--; 1654 handle->count--; 1655 return ext2fs_xattrs_write(handle); 1656 } 1657 } 1658 1659 /* no key found, success! */ 1660 return 0; 1661 } 1662 1663 errcode_t ext2fs_xattrs_open(ext2_filsys fs, ext2_ino_t ino, 1664 struct ext2_xattr_handle **handle) 1665 { 1666 struct ext2_xattr_handle *h; 1667 errcode_t err; 1668 1669 if (!ext2fs_has_feature_xattr(fs->super) && 1670 !ext2fs_has_feature_inline_data(fs->super)) 1671 return EXT2_ET_MISSING_EA_FEATURE; 1672 1673 err = ext2fs_get_memzero(sizeof(*h), &h); 1674 if (err) 1675 return err; 1676 1677 h->magic = EXT2_ET_MAGIC_EA_HANDLE; 1678 h->capacity = 4; 1679 err = ext2fs_get_arrayzero(h->capacity, sizeof(struct ext2_xattr), 1680 &h->attrs); 1681 if (err) { 1682 ext2fs_free_mem(&h); 1683 return err; 1684 } 1685 h->count = 0; 1686 h->ino = ino; 1687 h->fs = fs; 1688 *handle = h; 1689 return 0; 1690 } 1691 1692 errcode_t ext2fs_xattrs_close(struct ext2_xattr_handle **handle) 1693 { 1694 struct ext2_xattr_handle *h = *handle; 1695 1696 EXT2_CHECK_MAGIC(h, EXT2_ET_MAGIC_EA_HANDLE); 1697 xattrs_free_keys(h); 1698 ext2fs_free_mem(&h->attrs); 1699 ext2fs_free_mem(handle); 1700 return 0; 1701 } 1702 1703 errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count) 1704 { 1705 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1706 *count = handle->count; 1707 return 0; 1708 } 1709 1710 errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle, 1711 unsigned int *new_flags, unsigned int *old_flags) 1712 { 1713 EXT2_CHECK_MAGIC(handle, EXT2_ET_MAGIC_EA_HANDLE); 1714 if (old_flags) 1715 *old_flags = handle->flags; 1716 if (new_flags) 1717 handle->flags = *new_flags; 1718 return 0; 1719 }