news 2026/4/29 20:50:32

TLPI 第16章 读书笔记:Extended Attributes

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TLPI 第16章 读书笔记:Extended Attributes

笔记和练习博客总目录见:开始读TLPI。

本章介绍了扩展属性(EAs),它们允许以名称-值对的形式将任意元数据与文件 i 节点关联。EAs 在 Linux 2.6 版本中被添加。

16.1 Overview

EAs 用于实现访问控制列表(第17章)和文件功能(第39章)。然而,EAs 的设计足够通用,也可以用于其他目的。例如,EAs 可以用于记录文件版本号、文件的 MIME 类型或字符集信息,或(指向)图形图标。

SUSv3 中未指定 EAs。然而,在一些其他 UNIX 实现中提供了类似功能,尤其是现代 BSD(参见 extattr(2))和 Solaris 9 及更高版本(参见 fsattr(5))。

EAs 需要底层文件系统的支持。Btrfs、ext2、ext3、ext4、JFS、Reiserfs 和 XFS 都提供了这种支持。

每个文件系统对 EAs 的支持是可选的,由内核配置选项中的 “文件系统” 菜单控制。自 Linux 2.6.7 起,Reiserfs 支持 EAs。

EA namespaces
EAs 的名称形式为 namespace.name。命名空间组件用于将 EAs 分隔为功能上不同的类别。名称组件在给定命名空间内唯一标识一个 EA。

命名空间支持四个值:user、trusted、system 和 security。这四种类型的 EA 使用方式如下:

  • 用户 EAs 可以由无特权进程操作,但需遵守文件权限检查:要读取用户 EA 的值,需要文件的读取权限;要修改用户 EA 的值,需要文件的写入权限。(缺少所需权限会导致 EACCES 错误。)为了将用户 EAs 与 ext2、ext3、ext4 或 Reiserfs 文件系统上的文件关联,底层文件系统必须以 user_xattr 选项挂载:
$mount-ouser_xattr device directory
  • Trusted EA 像用户扩展属性一样,可以被用户进程操作。不同之处在于,操作Trusted EA 的进程必须具有特权(CAP_SYS_ADMIN)。
  • System EA由内核用于将系统对象与文件关联。目前,唯一支持的对象类型是访问控制列表(第17章)。
  • Security EA用于存储操作系统安全模块的文件安全标签,以及将能力与可执行文件关联(第39.3.2节)。Security EA最初是为支持安全增强型Linux(SELinux,http://www.nsa.gov/research/selinux/)而设计的。

一个 i-node 可能有多个关联的扩展属性(EA),这些属性可以位于相同的命名空间或不同的命名空间中。每个命名空间内的 EA 名称是不同的集合。在用户和受信任命名空间中,EA 名称可以是任意字符串。在系统命名空间中,仅允许内核明确许可的名称(例如,用于访问控制列表的名称)。

JFS 支持另一个命名空间 os2,这在其他文件系统中未实现。提供 os2 命名空间是为了支持传统的 OS/2 文件系统扩展属性。进程无需具有特权即可创建 os2 EA。

💡 那这些EAs谁在用?典型的包括SELinux用security.selinux存放安全上下文信息,Linux Capabilities使用security.capability存放细粒度权限信息。或者用户应用自定义其使用规则。

Creating and viewing EAs from the shell
在 shell 中,我们可以使用 setfattr(1) 和 getfattr(1) 命令来设置和查看文件的扩展属性(EAs):

$touchtfile# -n name, Specifies the name of the extended attribute to set.# -v value, Specifies the new value of the extended attribute.$ setfattr-nuser.x-v"The past is not dead."tfile $ setfattr-nuser.y-v"In fact, it's not even past."tfile $ getfattr-nuser.x tfile# file: tfileuser.x="The past is not dead."# -d, Dump the values of all matched extended attributes.$ getfattr-dtfile# file: tfileuser.x="The past is not dead."user.y="In fact, it's not even past."$ setfattr-nuser.x tfile $ getfattr-dtfile# file: tfileuser.x=""user.y="In fact, it's not even past."# -x name, Remove the named extended attribute entirely.$ setfattr-xuser.y tfile $ getfattr-dtfile# file: tfileuser.x=""$ $ getfattr-m- tfile# file: tfilesecurity.selinux user.x

前一个 shell 会话所演示的一个要点是,EA 的值可能是一个空字符串,这与未定义的 EA 不同。(在 shell 会话结束时,user.x 的值是空字符串,而 user.y 是未定义的。)

默认情况下,getfattr 只列出用户 EA 的值。可以使用 -m 选项来指定一个正则表达式模式,以选择要显示的 EA 名称:

$ getfattr-m'pattern'file

pattern 的默认值是^user..我们可以使用以下命令将所有 EA 列到一个文件中:

$ getfattr-m-file

16.2 Extended Attribute Implementation Details

在本节中,我们扩展前一节的概述,以补充一些关于 EA 实现的细节。

Restrictions on user extended attributes
只能将用户扩展属性(EAs)放置在文件和目录上。其他类型的文件由于以下原因被排除在外:

  • 对于符号链接,所有用户的所有权限都是启用的,并且这些权限无法更改。(如第18.2节中详细说明,符号链接的权限在Linux上没有意义。)这意味着权限不能用于阻止任意用户在符号链接上放置用户EA。解决此问题的方法是阻止所有用户在符号链接上创建用户EA。

  • 对于设备文件、套接字和FIFO,权限控制用户对执行底层对象I/O的访问。操纵这些权限以控制用户EA的创建会与此目的发生冲突。

此外,如果目录上设置了粘滞位(第15.4.5节),非特权进程就无法在其他用户拥有的目录上放置用户扩展属性(EA)。

这可以防止任意用户向像 /tmp 这样可公开写入的目录附加扩展属性(EA),因为这些目录允许任意用户操作目录上的扩展属性,但设置了粘滞位以防止用户删除目录中其他用户拥有的文件。

Implementation limits
Linux VFS 对所有文件系统的扩展属性(EA)施加了以下限制:

  • EA 名称的长度限制为 255 个字符。
  • EA 值限制为 64 kB。
    此外,一些文件系统对与文件相关的 EA 的大小和数量施加了更严格的限制:
  • 在 ext2、ext3 和 ext4 上,文件上所有 EA 的名称和值使用的总字节数限制为单个逻辑磁盘块的大小(第 14.3 节):1024、2048 或 4096 字节。
  • 在 JFS 上,文件上所有 EA 的名称和值使用的总字节数上限为 128 kB。

16.3 System Calls for Manipulating Extended Attributes

在本节中,我们将查看用于更新、检索和删除扩展属性(EA)的系统调用。

Creating and modifying EAs
setxattr()、lsetxattr() 和 fsetxattr() 系统调用设置文件某个扩展属性(EA)的值。

#include<sys/xattr.h>intsetxattr(constchar*pathname,constchar*name,constvoid*value,size_tsize,intflags);intlsetxattr(constchar*pathname,constchar*name,constvoid*value,size_tsize,intflags);intfsetxattr(intfd,constchar*name,constvoid*value,size_tsize,intflags);

这三个调用之间的差异类似于 stat()、lstat() 和 fstat()(第15.1节)之间的差异:

  • setxattr() 通过路径名识别文件,如果它是符号链接,则会取消引用该文件名;
  • lsetxattr() 通过路径名识别文件,但不会取消引用符号链接;
  • fsetxattr() 通过打开的文件描述符 fd 识别文件。

同样的区别也适用于本节余下部分描述的其他系统调用组。

name 参数是一个以空字符结尾的字符串,用于定义 EA 的名称。
value 参数是一个指向缓冲区的指针,用于定义 EA 的新值。
size 参数指定该缓冲区的长度。

默认情况下,如果具有给定名称的 EA 不存在,这些系统调用会创建一个新的 EA;如果 EA 已经存在,则会替换其值。
flags 参数提供了对这种行为的更精细控制。它可以指定为 0 以获得默认行为,或者指定为以下常量之一:

  • XATTR_CREATE
    如果具有给定名称的扩展属性(EA)已存在,则失败(EEXIST)。
  • XATTR_REPLACE
    如果具有给定名称的扩展属性(EA)尚不存在,则失败(ENODATA)。

下面是使用 setxattr() 创建用户扩展属性(EA)的示例:

char*value;value="The past is not dead.";if(setxattr(pathname,"user.x",value,strlen(value),0)==-1)errExit("setxattr");

Retrieving the value of an EA

getxattr()、lgetxattr() 和 fgetxattr() 系统调用用于获取扩展属性(EA)的值。

#include<sys/xattr.h>ssize_tgetxattr(constchar*pathname,constchar*name,void*value,size_tsize);ssize_tlgetxattr(constchar*pathname,constchar*name,void*value,size_tsize);ssize_tfgetxattr(intfd,constchar*name,void*value,size_tsize);

name 参数是一个以空字符结尾的字符串,用于标识我们想要获取其值的扩展属性(EA)。EA 值会被返回到由 value 指向的缓冲区中。这个缓冲区必须由调用者分配,并且其长度必须在 size 中指定。成功时,这些系统调用会返回复制到 value 中的字节数。

如果文件没有具有给定名称的属性,这些系统调用会以错误 ENODATA 失败。如果 size 太小,这些系统调用会以错误 ERANGE 失败。

可以将 size 指定为 0,在这种情况下 value 会被忽略,但系统调用仍然返回 EA 值的大小。这提供了一种机制,以便确定后续调用实际获取 EA 值所需的值缓冲区的大小。然而,请注意,我们仍然无法保证在随后尝试获取值时返回的大小足够。因为与此同时另一个进程可能已经将更大的值分配给该属性,或者完全移除了该属性

Removing an EA

removexattr()、lremovexattr() 和 fremovexattr() 系统调用从文件中移除 EA。

#include<sys/xattr.h>intremovexattr(constchar*pathname,constchar*name);intlremovexattr(constchar*pathname,constchar*name);intfremovexattr(intfd,constchar*name);

名称中给出的以空结尾的字符串标识要删除的扩展属性(EA)。
尝试删除不存在的扩展属性会失败,并返回错误 ENODATA。

Retrieving the names of all EAs associated with a file

listxattr()、llistxattr() 和 flistxattr() 系统调用返回一个包含与文件相关的所有扩展属性(EA)名称的列表。

#include<sys/xattr.h>ssize_tlistxattr(constchar*pathname,char*list,size_tsize);ssize_tllistxattr(constchar*pathname,char*list,size_tsize);ssize_tflistxattr(intfd,char*list,size_tsize);

EA 名称的列表以一系列以 null 结尾的字符串的形式返回,这些字符串存储在由 list 指向的缓冲区中。该缓冲区的大小必须在 size 中指定。成功时,这些系统调用会返回复制到 list 中的字节数。

💡 名称列表作为无序的以空字符结尾的字符数组返回(属性名称由空字节 (‘0’) 分隔),如下所示:

user.name1\0system.name1\0user.name2\0

与 getxattr() 类似,也可以将 size 指定为 0,此时 list 会被忽略,但系统调用会返回实际需要的缓冲区大小,以便随后调用能够实际检索 EA 名称列表(假设其保持不变)。

要检索与文件关联的 EA 名称列表,只需要文件可访问(即我们对 pathname 中包含的所有目录具有执行权限)。文件本身不需要任何权限。

出于安全原因,列表中返回的 EA 名称可能会排除调用进程无法访问的属性。例如,大多数文件系统会在非特权进程调用 listxattr() 时,从返回的列表中省略受信任属性。但请注意前一句中的“可能”,这表明文件系统实现没有义务这样做。因此,我们需要考虑到使用列表中返回的 EA 名称进行后续 getxattr() 调用可能失败的可能性,因为该进程没有获取该 EA 值所需的权限。(如果另一个进程在 listxattr() 和 getxattr() 调用之间删除了某个属性,也可能发生类似的失败。)

Example program

清单16-1中的程序检索并显示命令行中列出的所有文件的EA(扩展属性)的名称和值。对于每个文件,程序使用listxattr()来检索与文件关联的所有EA的名称,然后执行一个循环,对每个名称调用getxattr()一次,以检索相应的值。默认情况下,属性值以纯文本形式显示。如果提供了–x选项,则属性值以十六进制字符串显示。下面的Shell会话日志演示了该程序的使用:

$touchtfile $ setfattr-nuser.x-v"The past is not dead."tfile $ setfattr-nuser.y-v"In fact, it's not even past."tfile $ ./xattr_view tfile tfile:name=security.selinux;value=unconfined_u:object_r:user_home_t:s0name=user.x;value=The past is not dead.name=user.y;value=In fact, it's not even past.

Listing 16-1: Display file extended attributes

// xattr/xattr_view.c// 代码略

16.4 Summary

从版本 2.6 开始,Linux 支持扩展属性,这允许将任意元数据与文件关联,形式为名称-值对。

16.5 Exercise

参见 TLPI 第16章 练习:Extended Attributes。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 20:49:17

Phi-4-mini-reasoning模型API接口测试实战:使用Postman与Python脚本

Phi-4-mini-reasoning模型API接口测试实战&#xff1a;使用Postman与Python脚本 1. 引言&#xff1a;为什么需要API测试 当你部署好Phi-4-mini-reasoning模型后&#xff0c;API接口就成了与模型交互的唯一通道。作为测试工程师或开发者&#xff0c;你需要确保这个通道在各种情…

作者头像 李华
网站建设 2026/4/29 20:48:41

实现一个简单的正则表达式引擎

文章目录实现一个简单的正则表达式引擎 &#x1f680;正则表达式基础 &#x1f4d6;实现思路 &#x1f9e0;实现解析器&#xff08;Parser&#xff09;&#x1f50d;构建NFA &#x1f3d7;️实现匹配算法 ⚡整合引擎 &#x1f9e9;性能优化 &#x1f4a8;扩展功能 &#x1f527…

作者头像 李华
网站建设 2026/4/29 20:46:25

MCP 协议核心原理解密:Message、Transport 与 Capability 的深度拆解

系列导读 你现在看到的是《MCP 协议与工具调用体系深度实践:从原理到生产落地的全栈指南》的第 2/10 篇,当前这篇会重点解决:用协议级别的细节拆解,让读者能亲手解析一个 MCP 消息,而不仅仅是概念理解。 上一篇回顾:第 1 篇《MCP 协议的前世今生:为什么我们需要一个统…

作者头像 李华
网站建设 2026/4/29 20:46:24

C++20 Concepts:让模板编程从“黑魔法”走向“契约时代”

如果说 C 模板是泛型编程皇冠上的明珠&#xff0c;那么在 C20 之前&#xff0c;这颗明珠一直被一层名为 SFINAE 的迷雾笼罩。直到 Concepts&#xff08;概念&#xff09; 的出现&#xff0c;模板才真正拥有了类型安全、语义清晰、易于调试的现代化外衣。 本文将带你快速掌握 Co…

作者头像 李华
网站建设 2026/4/29 20:40:27

每日GitCode开源项目推荐:中小开发者的“神兵利器”

&#x1f680;嘿&#xff0c;各位开发者朋友&#xff01;今天咱们不聊那些遥不可及的超级大模型&#xff0c;专门来挖一挖 GitCode 上最近冒出来的、特别适合咱们中小团队和个人开发者使用的优质开源项目。这次筛选的标准很明确&#xff1a;上手快、功能实、能解决真问题。看看…

作者头像 李华