1 /*
2  *  Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3  *  Copyright (C) 2007 The Regents of the University of California.
4  *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5  *  Written by Brian Behlendorf <behlendorf1@llnl.gov>.
6  *  UCRL-CODE-235197
7  *
8  *  This file is part of the SPL, Solaris Porting Layer.
9  *
10  *  The SPL is free software; you can redistribute it and/or modify it
11  *  under the terms of the GNU General Public License as published by the
12  *  Free Software Foundation; either version 2 of the License, or (at your
13  *  option) any later version.
14  *
15  *  The SPL is distributed in the hope that it will be useful, but WITHOUT
16  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  *  for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #ifndef _SPL_CRED_H
25 #define	_SPL_CRED_H
26 
27 #include <linux/module.h>
28 #include <linux/cred.h>
29 #include <linux/sched.h>
30 #include <sys/types.h>
31 #include <sys/vfs.h>
32 
33 typedef struct cred cred_t;
34 
35 extern struct task_struct init_task;
36 
37 #define	kcred		((cred_t *)(init_task.cred))
38 #define	CRED()		((cred_t *)current_cred())
39 
40 /* Linux 4.9 API change, GROUP_AT was removed */
41 #ifndef GROUP_AT
42 #define	GROUP_AT(gi, i)	((gi)->gid[i])
43 #endif
44 
45 #define	KUID_TO_SUID(x)		(__kuid_val(x))
46 #define	KGID_TO_SGID(x)		(__kgid_val(x))
47 #define	SUID_TO_KUID(x)		(KUIDT_INIT(x))
48 #define	SGID_TO_KGID(x)		(KGIDT_INIT(x))
49 #define	KGIDP_TO_SGIDP(x)	(&(x)->val)
50 
51 extern zidmap_t *zfs_get_init_idmap(void);
52 
53 /* Check if the user ns is the initial one */
54 static inline boolean_t
55 zfs_is_init_userns(struct user_namespace *user_ns)
56 {
57 #if defined(CONFIG_USER_NS)
58 	return (user_ns == kcred->user_ns);
59 #else
60 	return (B_FALSE);
61 #endif
62 }
63 
64 static inline struct user_namespace *zfs_i_user_ns(struct inode *inode)
65 {
66 #ifdef HAVE_SUPER_USER_NS
67 	return (inode->i_sb->s_user_ns);
68 #else
69 	return (kcred->user_ns);
70 #endif
71 }
72 
73 static inline boolean_t zfs_no_idmapping(struct user_namespace *mnt_userns,
74     struct user_namespace *fs_userns)
75 {
76 	return (zfs_is_init_userns(mnt_userns) ||
77 	    mnt_userns == fs_userns);
78 }
79 
80 static inline uid_t zfs_uid_to_vfsuid(zidmap_t *mnt_userns,
81     struct user_namespace *fs_userns, uid_t uid)
82 {
83 	struct user_namespace *owner;
84 #ifdef HAVE_IOPS_CREATE_IDMAP
85 	if (mnt_userns == zfs_init_idmap)
86 		return (uid);
87 #endif
88 #ifdef HAVE_IDMAP_NO_USERNS
89 	struct user_namespace ns;
90 	ns.uid_map = mnt_userns->uid_map;
91 	owner = &ns;
92 #else
93 	owner = idmap_owner(mnt_userns);
94 #endif
95 	if (zfs_no_idmapping(owner, fs_userns))
96 		return (uid);
97 	if (!zfs_is_init_userns(fs_userns))
98 		uid = from_kuid(fs_userns, KUIDT_INIT(uid));
99 	if (uid == (uid_t)-1)
100 		return (uid);
101 	return (__kuid_val(make_kuid(owner, uid)));
102 }
103 
104 static inline gid_t zfs_gid_to_vfsgid(zidmap_t *mnt_userns,
105     struct user_namespace *fs_userns, gid_t gid)
106 {
107 	struct user_namespace *owner;
108 #ifdef HAVE_IOPS_CREATE_IDMAP
109 	if (mnt_userns == zfs_init_idmap)
110 		return (gid);
111 #endif
112 #ifdef HAVE_IDMAP_NO_USERNS
113 	struct user_namespace ns;
114 	ns.gid_map = mnt_userns->gid_map;
115 	owner = &ns;
116 #else
117 	owner = idmap_owner(mnt_userns);
118 #endif
119 	if (zfs_no_idmapping(owner, fs_userns))
120 		return (gid);
121 	if (!zfs_is_init_userns(fs_userns))
122 		gid = from_kgid(fs_userns, KGIDT_INIT(gid));
123 	if (gid == (gid_t)-1)
124 		return (gid);
125 	return (__kgid_val(make_kgid(owner, gid)));
126 }
127 
128 static inline uid_t zfs_vfsuid_to_uid(zidmap_t *mnt_userns,
129     struct user_namespace *fs_userns, uid_t uid)
130 {
131 	struct user_namespace *owner;
132 #ifdef HAVE_IOPS_CREATE_IDMAP
133 	if (mnt_userns == zfs_init_idmap)
134 		return (uid);
135 #endif
136 #ifdef HAVE_IDMAP_NO_USERNS
137 	struct user_namespace ns;
138 	ns.uid_map = mnt_userns->uid_map;
139 	owner = &ns;
140 #else
141 	owner = idmap_owner(mnt_userns);
142 #endif
143 	if (zfs_no_idmapping(owner, fs_userns))
144 		return (uid);
145 	uid = from_kuid(owner, KUIDT_INIT(uid));
146 	if (uid == (uid_t)-1)
147 		return (uid);
148 	if (zfs_is_init_userns(fs_userns))
149 		return (uid);
150 	return (__kuid_val(make_kuid(fs_userns, uid)));
151 }
152 
153 static inline gid_t zfs_vfsgid_to_gid(zidmap_t *mnt_userns,
154     struct user_namespace *fs_userns, gid_t gid)
155 {
156 	struct user_namespace *owner;
157 #ifdef HAVE_IOPS_CREATE_IDMAP
158 	if (mnt_userns == zfs_init_idmap)
159 		return (gid);
160 #endif
161 #ifdef HAVE_IDMAP_NO_USERNS
162 	struct user_namespace ns;
163 	ns.gid_map = mnt_userns->gid_map;
164 	owner = &ns;
165 #else
166 	owner = idmap_owner(mnt_userns);
167 #endif
168 	if (zfs_no_idmapping(owner, fs_userns))
169 		return (gid);
170 	gid = from_kgid(owner, KGIDT_INIT(gid));
171 	if (gid == (gid_t)-1)
172 		return (gid);
173 	if (zfs_is_init_userns(fs_userns))
174 		return (gid);
175 	return (__kgid_val(make_kgid(fs_userns, gid)));
176 }
177 
178 extern void crhold(cred_t *cr);
179 extern void crfree(cred_t *cr);
180 extern uid_t crgetuid(const cred_t *cr);
181 extern uid_t crgetruid(const cred_t *cr);
182 extern gid_t crgetgid(const cred_t *cr);
183 extern int crgetngroups(const cred_t *cr);
184 extern gid_t *crgetgroups(const cred_t *cr);
185 extern int groupmember(gid_t gid, const cred_t *cr);
186 #endif  /* _SPL_CRED_H */
187