1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * fs/sharefs/authentication.c
4 *
5 * Copyright (c) 2023 Huawei Device Co., Ltd.
6 */
7 #include "authentication.h"
8
perm_get_next_level(__u16 perm)9 static inline __u16 perm_get_next_level(__u16 perm)
10 {
11 __u16 level = (perm & SHAREFS_PERM_MASK) + 1;
12
13 if (level <= SHAREFS_PERM_OTHER)
14 return level;
15 else
16 return SHAREFS_PERM_OTHER;
17 }
18
fixup_perm_from_level(struct inode * dir,struct dentry * dentry)19 void fixup_perm_from_level(struct inode *dir, struct dentry *dentry)
20 {
21 struct sharefs_inode_info *hii = SHAREFS_I(dir);
22 struct inode *dinode = d_inode(dentry);
23 struct sharefs_inode_info *dinfo = SHAREFS_I(dinode);
24 const unsigned char* cur_name = dentry->d_name.name;
25 __u16 level = perm_get_next_level(hii->perm);
26 __u16 perm = 0;
27 int bid = 0;
28
29 if (IS_ERR_OR_NULL(dinode))
30 return;
31 dinode->i_uid = dir->i_uid;
32 dinode->i_gid = dir->i_gid;
33 switch (level) {
34 case SHAREFS_PERM_MNT:
35 bid = get_bundle_uid(SHAREFS_SB(dentry->d_sb),
36 dentry->d_name.name);
37 perm = level;
38 if (bid != 0) {
39 dinode->i_uid = KUIDT_INIT(bid);
40 dinode->i_gid = KGIDT_INIT(bid);
41 } else {
42 dinode->i_uid = ROOT_UID;
43 dinode->i_gid = ROOT_GID;
44 }
45 dinode->i_mode = (dinode->i_mode & S_IFMT) | SHAREFS_PERM_READONLY_DIR;
46 break;
47 case SHAREFS_PERM_DFS:
48 if (!strcmp(cur_name, SHAREFS_READ_DIR)) {
49 perm = SHAREFS_DIR_TYPE_READONLY | level;
50 sharefs_set_read_perm(dinode);
51 } else if (!strcmp(cur_name, SHAREFS_READWRITE_DIR)) {
52 perm = SHAREFS_DIR_TYPE_READWRITE | level;
53 sharefs_set_read_write_perm(dinode);
54 }
55 break;
56 case SHAREFS_PERM_OTHER:
57 if (is_read_only_auth(hii->perm)) {
58 perm = SHAREFS_DIR_TYPE_READONLY | SHAREFS_PERM_DFS;
59 sharefs_set_read_perm(dinode);
60 } else if (is_read_write_auth(hii->perm)) {
61 perm = SHAREFS_DIR_TYPE_READWRITE | SHAREFS_PERM_DFS;
62 sharefs_set_read_write_perm(dinode);
63 }
64 break;
65 default:
66 sharefs_err("sharedfs perm incorrect got default case, level:%u", level);
67 break;
68 }
69 dinfo->perm = perm;
70 }
71
sharefs_root_inode_perm_init(struct inode * root_inode)72 void sharefs_root_inode_perm_init(struct inode *root_inode)
73 {
74 struct sharefs_inode_info *hii = SHAREFS_I(root_inode);
75 hii->perm = SHAREFS_PERM_FIX;
76 }
77
78 #ifdef CONFIG_SHAREFS_SUPPORT_OVERRIDE
sharefs_override_file_fsids(struct inode * dir,__u16 * _perm)79 const struct cred *sharefs_override_file_fsids(struct inode *dir, __u16 *_perm)
80 {
81 struct cred *cred = NULL;
82 cred = prepare_creds();
83 if (!cred)
84 return NULL;
85
86 cred->fsuid = dir->i_uid;
87 cred->fsgid = dir->i_gid;
88 return override_creds(cred);
89 }
90
sharefs_revert_fsids(const struct cred * old_cred)91 void sharefs_revert_fsids(const struct cred *old_cred)
92 {
93 const struct cred *cur_cred;
94 cur_cred = current->cred;
95 revert_creds(old_cred);
96 put_cred(cur_cred);
97 }
98 #endif
99