1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <linux/sched.h>
44#include <linux/fs_struct.h>
45
46#include <linux/compat.h>
47#include <linux/thread_info.h>
48
49#define DEBUG_SUBSYSTEM S_LNET
50
51#include <linux/libcfs/libcfs.h>
52
53
54
55
56
57
58int cfs_curproc_groups_nr(void)
59{
60 int nr;
61
62 task_lock(current);
63 nr = current_cred()->group_info->ngroups;
64 task_unlock(current);
65 return nr;
66}
67
68void cfs_curproc_groups_dump(gid_t *array, int size)
69{
70 task_lock(current);
71 size = min_t(int, size, current_cred()->group_info->ngroups);
72 memcpy(array, current_cred()->group_info->blocks[0], size * sizeof(__u32));
73 task_unlock(current);
74}
75
76
77int current_is_in_group(gid_t gid)
78{
79 return in_group_p(gid);
80}
81
82
83#define cfs_cap_pack(cap) (cap)
84#define cfs_cap_unpack(cap) (cap)
85
86void cfs_cap_raise(cfs_cap_t cap)
87{
88 struct cred *cred;
89 if ((cred = prepare_creds())) {
90 cap_raise(cred->cap_effective, cfs_cap_unpack(cap));
91 commit_creds(cred);
92 }
93}
94
95void cfs_cap_lower(cfs_cap_t cap)
96{
97 struct cred *cred;
98 if ((cred = prepare_creds())) {
99 cap_lower(cred->cap_effective, cfs_cap_unpack(cap));
100 commit_creds(cred);
101 }
102}
103
104int cfs_cap_raised(cfs_cap_t cap)
105{
106 return cap_raised(current_cap(), cfs_cap_unpack(cap));
107}
108
109void cfs_kernel_cap_pack(kernel_cap_t kcap, cfs_cap_t *cap)
110{
111#if defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x19980330
112 *cap = cfs_cap_pack(kcap);
113#elif defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x20071026
114 *cap = cfs_cap_pack(kcap[0]);
115#elif defined(_KERNEL_CAPABILITY_VERSION) && _KERNEL_CAPABILITY_VERSION == 0x20080522
116
117 *cap = cfs_cap_pack(kcap.cap[0]);
118#else
119 #error "need correct _KERNEL_CAPABILITY_VERSION "
120#endif
121}
122
123void cfs_kernel_cap_unpack(kernel_cap_t *kcap, cfs_cap_t cap)
124{
125#if defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x19980330
126 *kcap = cfs_cap_unpack(cap);
127#elif defined (_LINUX_CAPABILITY_VERSION) && _LINUX_CAPABILITY_VERSION == 0x20071026
128 (*kcap)[0] = cfs_cap_unpack(cap);
129#elif defined(_KERNEL_CAPABILITY_VERSION) && _KERNEL_CAPABILITY_VERSION == 0x20080522
130 kcap->cap[0] = cfs_cap_unpack(cap);
131#else
132 #error "need correct _KERNEL_CAPABILITY_VERSION "
133#endif
134}
135
136cfs_cap_t cfs_curproc_cap_pack(void)
137{
138 cfs_cap_t cap;
139 cfs_kernel_cap_pack(current_cap(), &cap);
140 return cap;
141}
142
143void cfs_curproc_cap_unpack(cfs_cap_t cap)
144{
145 struct cred *cred;
146 if ((cred = prepare_creds())) {
147 cfs_kernel_cap_unpack(&cred->cap_effective, cap);
148 commit_creds(cred);
149 }
150}
151
152int cfs_capable(cfs_cap_t cap)
153{
154 return capable(cfs_cap_unpack(cap));
155}
156
157
158
159
160
161
162
163
164int current_is_32bit(void)
165{
166 return is_compat_task();
167}
168
169static int cfs_access_process_vm(struct task_struct *tsk, unsigned long addr,
170 void *buf, int len, int write)
171{
172
173
174 struct mm_struct *mm;
175 struct vm_area_struct *vma;
176 struct page *page;
177 void *old_buf = buf;
178
179 mm = get_task_mm(tsk);
180 if (!mm)
181 return 0;
182
183 down_read(&mm->mmap_sem);
184
185 while (len) {
186 int bytes, rc, offset;
187 void *maddr;
188
189 rc = get_user_pages(tsk, mm, addr, 1,
190 write, 1, &page, &vma);
191 if (rc <= 0)
192 break;
193
194 bytes = len;
195 offset = addr & (PAGE_SIZE-1);
196 if (bytes > PAGE_SIZE-offset)
197 bytes = PAGE_SIZE-offset;
198
199 maddr = kmap(page);
200 if (write) {
201 copy_to_user_page(vma, page, addr,
202 maddr + offset, buf, bytes);
203 set_page_dirty_lock(page);
204 } else {
205 copy_from_user_page(vma, page, addr,
206 buf, maddr + offset, bytes);
207 }
208 kunmap(page);
209 page_cache_release(page);
210 len -= bytes;
211 buf += bytes;
212 addr += bytes;
213 }
214 up_read(&mm->mmap_sem);
215 mmput(mm);
216
217 return buf - old_buf;
218}
219
220
221int cfs_get_environ(const char *key, char *value, int *val_len)
222{
223 struct mm_struct *mm;
224 char *buffer, *tmp_buf = NULL;
225 int buf_len = PAGE_CACHE_SIZE;
226 int key_len = strlen(key);
227 unsigned long addr;
228 int rc;
229 ENTRY;
230
231 buffer = kmalloc(buf_len, GFP_USER);
232 if (!buffer)
233 RETURN(-ENOMEM);
234
235 mm = get_task_mm(current);
236 if (!mm) {
237 kfree(buffer);
238 RETURN(-EINVAL);
239 }
240
241
242
243
244
245 if (down_read_trylock(&mm->mmap_sem) == 0)
246 return -EDEADLK;
247 up_read(&mm->mmap_sem);
248
249 addr = mm->env_start;
250 while (addr < mm->env_end) {
251 int this_len, retval, scan_len;
252 char *env_start, *env_end;
253
254 memset(buffer, 0, buf_len);
255
256 this_len = min_t(int, mm->env_end - addr, buf_len);
257 retval = cfs_access_process_vm(current, addr, buffer,
258 this_len, 0);
259 if (retval != this_len)
260 break;
261
262 addr += retval;
263
264
265
266 env_start = buffer;
267 scan_len = this_len;
268 while (scan_len) {
269 char *entry;
270 int entry_len;
271
272 env_end = memscan(env_start, '\0', scan_len);
273 LASSERT(env_end >= env_start &&
274 env_end <= env_start + scan_len);
275
276
277
278 if (unlikely(env_end - env_start == scan_len)) {
279
280 if (unlikely(scan_len == this_len)) {
281 CERROR("Too long env variable.\n");
282 GOTO(out, rc = -EINVAL);
283 }
284 addr -= scan_len;
285 break;
286 }
287
288 entry = env_start;
289 entry_len = env_end - env_start;
290
291
292 if (entry_len > key_len + 1 &&
293 !memcmp(entry, key, key_len)) {
294 entry += key_len + 1;
295 entry_len -= key_len + 1;
296
297 if (entry_len >= *val_len)
298 GOTO(out, rc = -EOVERFLOW);
299
300 memcpy(value, entry, entry_len);
301 *val_len = entry_len;
302 GOTO(out, rc = 0);
303 }
304
305 scan_len -= (env_end - env_start + 1);
306 env_start = env_end + 1;
307 }
308 }
309 GOTO(out, rc = -ENOENT);
310
311out:
312 mmput(mm);
313 kfree((void *)buffer);
314 if (tmp_buf)
315 kfree((void *)tmp_buf);
316 return rc;
317}
318EXPORT_SYMBOL(cfs_get_environ);
319
320EXPORT_SYMBOL(cfs_curproc_groups_nr);
321EXPORT_SYMBOL(cfs_curproc_groups_dump);
322EXPORT_SYMBOL(current_is_in_group);
323EXPORT_SYMBOL(cfs_cap_raise);
324EXPORT_SYMBOL(cfs_cap_lower);
325EXPORT_SYMBOL(cfs_cap_raised);
326EXPORT_SYMBOL(cfs_curproc_cap_pack);
327EXPORT_SYMBOL(cfs_curproc_cap_unpack);
328EXPORT_SYMBOL(cfs_capable);
329EXPORT_SYMBOL(current_is_32bit);
330
331
332
333
334
335
336
337
338
339
340