1139749Simp/* SPDX-License-Identifier: GPL-2.0 */
2113584Ssimokawa#include <linux/fs.h>
3103285Sikob
4103285Sikob#define DEVCG_ACC_MKNOD 1
5103285Sikob#define DEVCG_ACC_READ  2
6103285Sikob#define DEVCG_ACC_WRITE 4
7103285Sikob#define DEVCG_ACC_MASK (DEVCG_ACC_MKNOD | DEVCG_ACC_READ | DEVCG_ACC_WRITE)
8103285Sikob
9103285Sikob#define DEVCG_DEV_BLOCK 1
10103285Sikob#define DEVCG_DEV_CHAR  2
11103285Sikob#define DEVCG_DEV_ALL   4  /* this represents all devices */
12103285Sikob
13103285Sikob
14103285Sikob#if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
15103285Sikobint devcgroup_check_permission(short type, u32 major, u32 minor,
16103285Sikob			       short access);
17103285Sikobstatic inline int devcgroup_inode_permission(struct inode *inode, int mask)
18103285Sikob{
19103285Sikob	short type, access = 0;
20103285Sikob
21103285Sikob	if (likely(!inode->i_rdev))
22103285Sikob		return 0;
23103285Sikob
24103285Sikob	if (S_ISBLK(inode->i_mode))
25103285Sikob		type = DEVCG_DEV_BLOCK;
26103285Sikob	else if (S_ISCHR(inode->i_mode))
27103285Sikob		type = DEVCG_DEV_CHAR;
28103285Sikob	else
29103285Sikob		return 0;
30103285Sikob
31103285Sikob	if (mask & MAY_WRITE)
32103285Sikob		access |= DEVCG_ACC_WRITE;
33103285Sikob	if (mask & MAY_READ)
34103285Sikob		access |= DEVCG_ACC_READ;
35103285Sikob
36127468Ssimokawa	return devcgroup_check_permission(type, imajor(inode), iminor(inode),
37119418Sobrien					  access);
38119418Sobrien}
39127468Ssimokawa
40119418Sobrienstatic inline int devcgroup_inode_mknod(int mode, dev_t dev)
41103285Sikob{
42103285Sikob	short type;
43103285Sikob
44103285Sikob	if (!S_ISBLK(mode) && !S_ISCHR(mode))
45103285Sikob		return 0;
46103285Sikob
47103285Sikob	if (S_ISCHR(mode) && dev == WHITEOUT_DEV)
48103285Sikob		return 0;
49127468Ssimokawa
50120660Ssimokawa	if (S_ISBLK(mode))
51120660Ssimokawa		type = DEVCG_DEV_BLOCK;
52120660Ssimokawa	else
53120660Ssimokawa		type = DEVCG_DEV_CHAR;
54103285Sikob
55103285Sikob	return devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
56113584Ssimokawa					  DEVCG_ACC_MKNOD);
57103285Sikob}
58103285Sikob
59103285Sikob#else
60103285Sikobstatic inline int devcgroup_check_permission(short type, u32 major, u32 minor,
61122228Ssimokawa			       short access)
62103285Sikob{ return 0; }
63127468Ssimokawastatic inline int devcgroup_inode_permission(struct inode *inode, int mask)
64127468Ssimokawa{ return 0; }
65127468Ssimokawastatic inline int devcgroup_inode_mknod(int mode, dev_t dev)
66127468Ssimokawa{ return 0; }
67127468Ssimokawa#endif
68103285Sikob