关于VERIFY_OCTAL_PERMISSIONS权限检查

修改内核创建/sys文件系统下的文件的权限时

将代码从 __ATTR(type, 0644, xx_show, NULL);
改为 __ATTR(type, 0666, xx_show, NULL);
编译时会报错:

include/linux/bug.h:33:45: error: negative width in bit-field '<anonymous>'
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
^
include/linux/kernel.h:853:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
BUILD_BUG_ON_ZERO((perms) & 2) + \
^
include/linux/sysfs.h:75:12: note: in expansion of macro 'VERIFY_OCTAL_PERMISSIONS'
.mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \
^
arch/powerpc/platforms/powernv/opal-elog.c:85:2: note: in expansion of macro '__ATTR'
__ATTR(id, 0666, elog_id_show, NULL);
^
include/linux/bug.h:33:45: error: negative width in bit-field '<anonymous>'
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
^
include/linux/kernel.h:853:3: note: in expansion of macro 'BUILD_BUG_ON_ZERO'
BUILD_BUG_ON_ZERO((perms) & 2) + \
^
include/linux/sysfs.h:75:12: note: in expansion of macro 'VERIFY_OCTAL_PERMISSIONS'
.mode = VERIFY_OCTAL_PERMISSIONS(_mode) }, \
^
arch/powerpc/platforms/powernv/opal-elog.c:87:2: note: in expansion of macro '__ATTR'
__ATTR(type, 0666, xx_show, NULL);

问题出自宏VERIFY_OCTAL_PERMISSIONS对权限的检查:

/* Permissions on a sysfs file: you didn't miss the 0 prefix did you? */
#define VERIFY_OCTAL_PERMISSIONS(perms)                                 \
        (BUILD_BUG_ON_ZERO((perms) < 0) +                               \
         BUILD_BUG_ON_ZERO((perms) > 0777) +                            \
         /* User perms >= group perms >= other perms */                 \
         BUILD_BUG_ON_ZERO(((perms) >> 6) < (((perms) >> 3) & 7)) +     \
         BUILD_BUG_ON_ZERO((((perms) >> 3) & 7) < ((perms) & 7)) +      \
         /* Other writable?  Generally considered a bad idea. */        \
         BUILD_BUG_ON_ZERO((perms) & 2) +                               \
         (perms))

这里从注释上也看的比较清晰权限的要求:
1.User perms >= group perms >= other perms
2. Other writable? Generally considered a bad idea.

1.所有者权限>=组用户权限>=其他人权限
也就是说 类似0466的这种权限是不允许的
2.这个检查不允许其他用户写的权限

这个宏看起来比较难看懂,我们仔细来分析一下:

入参是一个8进制数,注释也提示了我们是需要0开头的。

8进制数右移6位【perms) >> 6】就是取所有者权限
8进制数右移3位取低三位【perms) >> 3 & 7】就是取组权限

BUILD_BUG_ON_ZERO (x)
当x==0时编译会报错
当x!=0 时能够正常运行,结果为0

然后简化一下宏:

#define VERIFY_OCTAL_PERMISSIONS(perms) 
(BUILD_BUG_ON_ZERO(perms在边界值内?)+    \
BUILD_BUG_ON_ZERO(所有者权限<组权限)+   \
BUILD_BUG_ON_ZERO(组权限<其他用户权限)+ \
BUILD_BUG_ON_ZERO(其他用户权限可写)+    \
(perms)

)

这个宏的结果要么报错要么还是原来的值。

这里我们需要其他用户也要有写的权限就把BUILD_BUG_ON_ZERO((perms) & 2) 去掉就好了。

最后我们看看BUILD_BUG_ON_ZERO时怎么实现检查的,好奇。

#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
  1. (e): 表达式e的声明
  2. !!(e): 对e的结果进行两次求非。即如果e开始是0的话,结果就是0;如果e不为0,则结果为1。
  3. –!!(e): 再乘-1。如果第2步结果为0,则仍为0;否则结果为-1。
  4. struct { int : –!!(0); } –> struct { int : 0; } : 如果e的结果为0,则我们声明一个结构体拥有一个int型的数据域,并且规定它所占的位的个数为0。这没有任何问题,我们认为一切正常。
  5. struct { int : –!!(1); } –> struct { int : –1; } : 如果e的结果非0,结构体的int型数据域的位域将变为一个负数,将位域声明为负数这是一个语法的错误。
  6. 现在要么结果为声明了一个位域为0的结构体,要么出现位域为负数编译出错;如果能正确编译,然后我们对该结构体进行sizeof操作,得到一个类型为size_t的结果,值为0。

再总结一下,BUILD_BUG_ON_ZERO(e) 表示的就是若表达式e结果为0,则编译通过,该宏的值也为0;若表达式e的结果不为0,则编译不通过。

后记,发现即便更改了权限检查,运行时也会报错

WARNING: CPU: 0 PID: 219 at fs/sysfs/group.c:61 internal_create_group+0x1e4/0x268()
Attribute direction: Invalid permissions 0666
Modules linked in:
CPU: 0 PID: 219 Comm: sh Not tainted 4.1.15 #13
Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[<c0110254>] (unwind_backtrace) from [<c010b660>] (show_stack+0x10/0x14)
[<c010b660>] (show_stack) from [<c0bf3338>] (dump_stack+0x7c/0xbc)
[<c0bf3338>] (dump_stack) from [<c0135520>] (warn_slowpath_fmt+0x90/0xc8)
[<c0135520>] (warn_slowpath_fmt) from [<c02aac28>] (internal_create_group+0x1e4/0x268)
[<c02aac28>] (internal_create_group) from [<c02aaff0>] (sysfs_create_groups+0x4c/0x110)
[<c02aaff0>] (sysfs_create_groups) from [<c05f0e70>] (device_add+0x348/0x570)
[<c05f0e70>] (device_add) from [<c05f131c>] (device_create_groups_vargs+0x128/0x138)
[<c05f131c>] (device_create_groups_vargs) from [<c05f13a4>] (device_create_with_groups+0x24/0x2c)
[<c05f13a4>] (device_create_with_groups) from [<c051b444>] (gpiod_export+0x13c/0x1c0)
[<c051b444>] (gpiod_export) from [<c051b51c>] (export_store+0x54/0xc0)
[<c051b51c>] (export_store) from [<c02a9424>] (kernfs_fop_write+0xb8/0x19c)
[<c02a9424>] (kernfs_fop_write) from [<c023df80>] (vfs_write+0xa0/0x1c4)
[<c023df80>] (vfs_write) from [<c023e7f8>] (SyS_write+0x44/0x9c)
[<c023e7f8>] (SyS_write) from [<c01076c0>] (ret_fast_syscall+0x0/0x3c)
---[ end trace 66868f3da9543a66 ]---

还需要更改fs/sysfs/group.c ,把664 改成666


WARN(mode & ~(SYSFS_PREALLOC | 0664),
                            "Attribute %s: Invalid permissions 0%o\n",
                             (*attr)->name, mode);

 mode &= SYSFS_PREALLOC | 0664;
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值