ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Email-reading: Add ioctls to get/set the ext4 superblock uuid

2022-07-07 18:36:01  阅读:162  来源: 互联网

标签:__ set uuid fsuuid get user address define


Origin Patch[PATCH] Add ioctls to get/set the ext4 superblock uuid.

Note1: Userspace abi change should cc more

This is a userspace abi change; it really should cc linux-fsdevel and linux-api.

Patch 增加了 EXT4_IOC_GETFSUUID 以及对应的 SET 接口,因此抄送 linux-api。另外 比较大的 fs 修改需要抄送 linux-fsdevel

另外如果对用户使用有修改,需要修改 man 手册:[PATCH] Add support for get/set UUID ioctls.

如果可以的话,增加 fstest 测试用例:[PATCH] ext4/056: add a check to make sure ext4 uuid ioctls get/set during fsstress.

Note2: Direction is a separate part in the ioctl command value

+#define EXT4_IOC_GETFSUUID		_IOR('f', 44, struct fsuuid)
+#define EXT4_IOC_SETFSUUID		_IOW('f', 45, struct fsuuid)

One thing I've noticed people rarely do with a get/set ioctl pair -- the _IOR and _IOW macros encode the direction (R/W) in the ioctl number, which means that you don't need to use both 44 and 45 here. We get 8 bits of namespace ('f') and 8 bits of call number (44), and while they're generally not in /that/ short supply, a u16 will eventually fill up.
If you want to be paranoid, you could also encode a BUILD_BUG_ON to check that they're not the same.

ioctl 请求编号是 32 位产量,通常通过 <asm/ioctl.h> 中定义的宏来构建[1]。下表描述了各 bit 的含义(和代码里有些出入,以理解为主):

0-8 bits 9-16 bits 17-24 bits 25-32 bits
number magic arg size direction

可以看到 direction 域包含了 ioctl 的方向。因此 EXT4_IOC_GETFSUUID 和 EXT4_IOC_SETFSUUID 完全可以用一个 number。

# define _IOC_WRITE	1U
# define _IOC_READ	2U

#define _IOC(dir,type,nr,size) \
	(((dir)  << _IOC_DIRSHIFT) | \
	 ((type) << _IOC_TYPESHIFT) | \
	 ((nr)   << _IOC_NRSHIFT) | \
	 ((size) << _IOC_SIZESHIFT))

#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))

Note3: Use explicitly sized menber (ioctl)

+struct fsuuid {
+	size_t len;

size_t... is a mess for userspace ABI. If the kernel is running in a multiarch environment (e.g. i386 program running on x64 kernel) then you'll have to make sure that the field length is what you think it is. Given the current typedef hell w.r.t. size_t, I suggest making life easier on the reviewers and making @len explicitly sized.
Also, please put in a @flags argument just in case someone someday needs to add some.

Note 4: Use unsized VLA instead of a pointer (ioctl)

+	__u8 __user *b;

Putting a pointer in an ioctl struct argument is a /very/ bad idea, because doing so (a) makes it harder for things like seccomp to inspect arguments, and (b) usually means you have to implement a bunch of fugly compat ioctl thunking code for multiarch systems (e.g. i386 program running on x64 kernel) to extract the pointer and convert it to a native pointer.

You /could/ avoid both of these problems by requiring that the uuid data be stored in an unsized VLA at the end of the struct:

	struct fsuuid {
		__u32	fu_len;
		__u32	fu_flags;

		__u8	fu_uuid[];
	};

Then your set uuid validation code looks like this:

	int ret = 0;
	__u8 uuid[UUID_SIZE];
	struct fsuuid fsuuid;

	if (copy_from_user(&fsuuid, ufsuuid, sizeof(fsuuid)))
		return -EFAULT;

	if (fsuuid.fu_flags || fsuuid.fu_len != UUID_SIZE)
		return -EINVAL;

	if (copy_from_user(uuid, &fsuuid.fu_uuid[0], UUID_SIZE))
		return -EFAULT;

	/* actually set uuid... */

零长数组的使用,参考 Zero Length (Using the GNU Compiler Collection (GCC))


V2 Patch[PATCH v2] Add ioctls to get/set the ext4 superblock uuid.

Question1: __user 应该怎么用?有什么用?

+struct fsuuid {
+	__u32       fu_len;
+	__u32       fu_flags;
+	__u8 __user fu_uuid[];

__user is unnecessary here -- it applies to pointers, not to struct members.

sparse 工具 [2] 使用 __user 检查是否对用户空间指针存在解引用的情况,所以应用对象是指针。

__user 定义如下,这里的 address_space 指的是真正的地址空间,而不是 fs 里那个冒牌货 :p。另外 address_space(__user) 这样的表述很奇怪,追踪了下是 18 年 sparse 支持根据标识符定义 address_space 了,所以有人把原来的 address_space(1) 改成了现在这样 [3]

另外关于其他宏的用法可以参考 聊一聊linux内核中的基础工具库(2) Sparse - 知乎

/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
#ifdef __CHECKER__
/* address spaces */
# define __kernel	__attribute__((address_space(0)))
# define __user		__attribute__((noderef, address_space(__user)))
# define __iomem	__attribute__((noderef, address_space(__iomem)))
# define __percpu	__attribute__((noderef, address_space(__percpu)))
# define __rcu		__attribute__((noderef, address_space(__rcu)))

  1. ioctl(2) - Linux manual page ↩︎

  2. Sparse: a look under the hood [LWN.net] ↩︎

  3. sparse: use identifiers to define address spaces - Linux kernel source tree ↩︎

标签:__,set,uuid,fsuuid,get,user,address,define
来源: https://www.cnblogs.com/liuchao719/p/Email-reading-22_07_07.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有