• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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