1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593SmuzhiyunExtended Attributes 4*4882a593Smuzhiyun------------------- 5*4882a593Smuzhiyun 6*4882a593SmuzhiyunExtended attributes (xattrs) are typically stored in a separate data 7*4882a593Smuzhiyunblock on the disk and referenced from inodes via ``inode.i_file_acl*``. 8*4882a593SmuzhiyunThe first use of extended attributes seems to have been for storing file 9*4882a593SmuzhiyunACLs and other security data (selinux). With the ``user_xattr`` mount 10*4882a593Smuzhiyunoption it is possible for users to store extended attributes so long as 11*4882a593Smuzhiyunall attribute names begin with “user”; this restriction seems to have 12*4882a593Smuzhiyundisappeared as of Linux 3.0. 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunThere are two places where extended attributes can be found. The first 15*4882a593Smuzhiyunplace is between the end of each inode entry and the beginning of the 16*4882a593Smuzhiyunnext inode entry. For example, if inode.i\_extra\_isize = 28 and 17*4882a593Smuzhiyunsb.inode\_size = 256, then there are 256 - (128 + 28) = 100 bytes 18*4882a593Smuzhiyunavailable for in-inode extended attribute storage. The second place 19*4882a593Smuzhiyunwhere extended attributes can be found is in the block pointed to by 20*4882a593Smuzhiyun``inode.i_file_acl``. As of Linux 3.11, it is not possible for this 21*4882a593Smuzhiyunblock to contain a pointer to a second extended attribute block (or even 22*4882a593Smuzhiyunthe remaining blocks of a cluster). In theory it is possible for each 23*4882a593Smuzhiyunattribute's value to be stored in a separate data block, though as of 24*4882a593SmuzhiyunLinux 3.11 the code does not permit this. 25*4882a593Smuzhiyun 26*4882a593SmuzhiyunKeys are generally assumed to be ASCIIZ strings, whereas values can be 27*4882a593Smuzhiyunstrings or binary data. 28*4882a593Smuzhiyun 29*4882a593SmuzhiyunExtended attributes, when stored after the inode, have a header 30*4882a593Smuzhiyun``ext4_xattr_ibody_header`` that is 4 bytes long: 31*4882a593Smuzhiyun 32*4882a593Smuzhiyun.. list-table:: 33*4882a593Smuzhiyun :widths: 8 8 24 40 34*4882a593Smuzhiyun :header-rows: 1 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun * - Offset 37*4882a593Smuzhiyun - Type 38*4882a593Smuzhiyun - Name 39*4882a593Smuzhiyun - Description 40*4882a593Smuzhiyun * - 0x0 41*4882a593Smuzhiyun - \_\_le32 42*4882a593Smuzhiyun - h\_magic 43*4882a593Smuzhiyun - Magic number for identification, 0xEA020000. This value is set by the 44*4882a593Smuzhiyun Linux driver, though e2fsprogs doesn't seem to check it(?) 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunThe beginning of an extended attribute block is in 47*4882a593Smuzhiyun``struct ext4_xattr_header``, which is 32 bytes long: 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun.. list-table:: 50*4882a593Smuzhiyun :widths: 8 8 24 40 51*4882a593Smuzhiyun :header-rows: 1 52*4882a593Smuzhiyun 53*4882a593Smuzhiyun * - Offset 54*4882a593Smuzhiyun - Type 55*4882a593Smuzhiyun - Name 56*4882a593Smuzhiyun - Description 57*4882a593Smuzhiyun * - 0x0 58*4882a593Smuzhiyun - \_\_le32 59*4882a593Smuzhiyun - h\_magic 60*4882a593Smuzhiyun - Magic number for identification, 0xEA020000. 61*4882a593Smuzhiyun * - 0x4 62*4882a593Smuzhiyun - \_\_le32 63*4882a593Smuzhiyun - h\_refcount 64*4882a593Smuzhiyun - Reference count. 65*4882a593Smuzhiyun * - 0x8 66*4882a593Smuzhiyun - \_\_le32 67*4882a593Smuzhiyun - h\_blocks 68*4882a593Smuzhiyun - Number of disk blocks used. 69*4882a593Smuzhiyun * - 0xC 70*4882a593Smuzhiyun - \_\_le32 71*4882a593Smuzhiyun - h\_hash 72*4882a593Smuzhiyun - Hash value of all attributes. 73*4882a593Smuzhiyun * - 0x10 74*4882a593Smuzhiyun - \_\_le32 75*4882a593Smuzhiyun - h\_checksum 76*4882a593Smuzhiyun - Checksum of the extended attribute block. 77*4882a593Smuzhiyun * - 0x14 78*4882a593Smuzhiyun - \_\_u32 79*4882a593Smuzhiyun - h\_reserved[3] 80*4882a593Smuzhiyun - Zero. 81*4882a593Smuzhiyun 82*4882a593SmuzhiyunThe checksum is calculated against the FS UUID, the 64-bit block number 83*4882a593Smuzhiyunof the extended attribute block, and the entire block (header + 84*4882a593Smuzhiyunentries). 85*4882a593Smuzhiyun 86*4882a593SmuzhiyunFollowing the ``struct ext4_xattr_header`` or 87*4882a593Smuzhiyun``struct ext4_xattr_ibody_header`` is an array of 88*4882a593Smuzhiyun``struct ext4_xattr_entry``; each of these entries is at least 16 bytes 89*4882a593Smuzhiyunlong. When stored in an external block, the ``struct ext4_xattr_entry`` 90*4882a593Smuzhiyunentries must be stored in sorted order. The sort order is 91*4882a593Smuzhiyun``e_name_index``, then ``e_name_len``, and finally ``e_name``. 92*4882a593SmuzhiyunAttributes stored inside an inode do not need be stored in sorted order. 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun.. list-table:: 95*4882a593Smuzhiyun :widths: 8 8 24 40 96*4882a593Smuzhiyun :header-rows: 1 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun * - Offset 99*4882a593Smuzhiyun - Type 100*4882a593Smuzhiyun - Name 101*4882a593Smuzhiyun - Description 102*4882a593Smuzhiyun * - 0x0 103*4882a593Smuzhiyun - \_\_u8 104*4882a593Smuzhiyun - e\_name\_len 105*4882a593Smuzhiyun - Length of name. 106*4882a593Smuzhiyun * - 0x1 107*4882a593Smuzhiyun - \_\_u8 108*4882a593Smuzhiyun - e\_name\_index 109*4882a593Smuzhiyun - Attribute name index. There is a discussion of this below. 110*4882a593Smuzhiyun * - 0x2 111*4882a593Smuzhiyun - \_\_le16 112*4882a593Smuzhiyun - e\_value\_offs 113*4882a593Smuzhiyun - Location of this attribute's value on the disk block where it is stored. 114*4882a593Smuzhiyun Multiple attributes can share the same value. For an inode attribute 115*4882a593Smuzhiyun this value is relative to the start of the first entry; for a block this 116*4882a593Smuzhiyun value is relative to the start of the block (i.e. the header). 117*4882a593Smuzhiyun * - 0x4 118*4882a593Smuzhiyun - \_\_le32 119*4882a593Smuzhiyun - e\_value\_inum 120*4882a593Smuzhiyun - The inode where the value is stored. Zero indicates the value is in the 121*4882a593Smuzhiyun same block as this entry. This field is only used if the 122*4882a593Smuzhiyun INCOMPAT\_EA\_INODE feature is enabled. 123*4882a593Smuzhiyun * - 0x8 124*4882a593Smuzhiyun - \_\_le32 125*4882a593Smuzhiyun - e\_value\_size 126*4882a593Smuzhiyun - Length of attribute value. 127*4882a593Smuzhiyun * - 0xC 128*4882a593Smuzhiyun - \_\_le32 129*4882a593Smuzhiyun - e\_hash 130*4882a593Smuzhiyun - Hash value of attribute name and attribute value. The kernel doesn't 131*4882a593Smuzhiyun update the hash for in-inode attributes, so for that case this value 132*4882a593Smuzhiyun must be zero, because e2fsck validates any non-zero hash regardless of 133*4882a593Smuzhiyun where the xattr lives. 134*4882a593Smuzhiyun * - 0x10 135*4882a593Smuzhiyun - char 136*4882a593Smuzhiyun - e\_name[e\_name\_len] 137*4882a593Smuzhiyun - Attribute name. Does not include trailing NULL. 138*4882a593Smuzhiyun 139*4882a593SmuzhiyunAttribute values can follow the end of the entry table. There appears to 140*4882a593Smuzhiyunbe a requirement that they be aligned to 4-byte boundaries. The values 141*4882a593Smuzhiyunare stored starting at the end of the block and grow towards the 142*4882a593Smuzhiyunxattr\_header/xattr\_entry table. When the two collide, the overflow is 143*4882a593Smuzhiyunput into a separate disk block. If the disk block fills up, the 144*4882a593Smuzhiyunfilesystem returns -ENOSPC. 145*4882a593Smuzhiyun 146*4882a593SmuzhiyunThe first four fields of the ``ext4_xattr_entry`` are set to zero to 147*4882a593Smuzhiyunmark the end of the key list. 148*4882a593Smuzhiyun 149*4882a593SmuzhiyunAttribute Name Indices 150*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~ 151*4882a593Smuzhiyun 152*4882a593SmuzhiyunLogically speaking, extended attributes are a series of key=value pairs. 153*4882a593SmuzhiyunThe keys are assumed to be NULL-terminated strings. To reduce the amount 154*4882a593Smuzhiyunof on-disk space that the keys consume, the beginning of the key string 155*4882a593Smuzhiyunis matched against the attribute name index. If a match is found, the 156*4882a593Smuzhiyunattribute name index field is set, and matching string is removed from 157*4882a593Smuzhiyunthe key name. Here is a map of name index values to key prefixes: 158*4882a593Smuzhiyun 159*4882a593Smuzhiyun.. list-table:: 160*4882a593Smuzhiyun :widths: 16 64 161*4882a593Smuzhiyun :header-rows: 1 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun * - Name Index 164*4882a593Smuzhiyun - Key Prefix 165*4882a593Smuzhiyun * - 0 166*4882a593Smuzhiyun - (no prefix) 167*4882a593Smuzhiyun * - 1 168*4882a593Smuzhiyun - “user.” 169*4882a593Smuzhiyun * - 2 170*4882a593Smuzhiyun - “system.posix\_acl\_access” 171*4882a593Smuzhiyun * - 3 172*4882a593Smuzhiyun - “system.posix\_acl\_default” 173*4882a593Smuzhiyun * - 4 174*4882a593Smuzhiyun - “trusted.” 175*4882a593Smuzhiyun * - 6 176*4882a593Smuzhiyun - “security.” 177*4882a593Smuzhiyun * - 7 178*4882a593Smuzhiyun - “system.” (inline\_data only?) 179*4882a593Smuzhiyun * - 8 180*4882a593Smuzhiyun - “system.richacl” (SuSE kernels only?) 181*4882a593Smuzhiyun 182*4882a593SmuzhiyunFor example, if the attribute key is “user.fubar”, the attribute name 183*4882a593Smuzhiyunindex is set to 1 and the “fubar” name is recorded on disk. 184*4882a593Smuzhiyun 185*4882a593SmuzhiyunPOSIX ACLs 186*4882a593Smuzhiyun~~~~~~~~~~ 187*4882a593Smuzhiyun 188*4882a593SmuzhiyunPOSIX ACLs are stored in a reduced version of the Linux kernel (and 189*4882a593Smuzhiyunlibacl's) internal ACL format. The key difference is that the version 190*4882a593Smuzhiyunnumber is different (1) and the ``e_id`` field is only stored for named 191*4882a593Smuzhiyunuser and group ACLs. 192