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#define DEBUG_SUBSYSTEM S_SEC
44#include <lu_object.h>
45#include <lustre_acl.h>
46#include <lustre_eacl.h>
47#include <obd_support.h>
48
49#ifdef CONFIG_FS_POSIX_ACL
50
51#define CFS_ACL_XATTR_VERSION POSIX_ACL_XATTR_VERSION
52
53enum {
54 ES_UNK = 0,
55 ES_UNC = 1,
56 ES_MOD = 2,
57 ES_ADD = 3,
58 ES_DEL = 4
59};
60
61static inline void lustre_ext_acl_le_to_cpu(ext_acl_xattr_entry *d,
62 ext_acl_xattr_entry *s)
63{
64 d->e_tag = le16_to_cpu(s->e_tag);
65 d->e_perm = le16_to_cpu(s->e_perm);
66 d->e_id = le32_to_cpu(s->e_id);
67 d->e_stat = le32_to_cpu(s->e_stat);
68}
69
70static inline void lustre_ext_acl_cpu_to_le(ext_acl_xattr_entry *d,
71 ext_acl_xattr_entry *s)
72{
73 d->e_tag = cpu_to_le16(s->e_tag);
74 d->e_perm = cpu_to_le16(s->e_perm);
75 d->e_id = cpu_to_le32(s->e_id);
76 d->e_stat = cpu_to_le32(s->e_stat);
77}
78
79static inline void lustre_posix_acl_le_to_cpu(posix_acl_xattr_entry *d,
80 posix_acl_xattr_entry *s)
81{
82 d->e_tag = le16_to_cpu(s->e_tag);
83 d->e_perm = le16_to_cpu(s->e_perm);
84 d->e_id = le32_to_cpu(s->e_id);
85}
86
87static inline void lustre_posix_acl_cpu_to_le(posix_acl_xattr_entry *d,
88 posix_acl_xattr_entry *s)
89{
90 d->e_tag = cpu_to_le16(s->e_tag);
91 d->e_perm = cpu_to_le16(s->e_perm);
92 d->e_id = cpu_to_le32(s->e_id);
93}
94
95
96
97static int lustre_posix_acl_xattr_reduce_space(posix_acl_xattr_header **header,
98 int old_count, int new_count)
99{
100 int old_size = CFS_ACL_XATTR_SIZE(old_count, posix_acl_xattr);
101 int new_size = CFS_ACL_XATTR_SIZE(new_count, posix_acl_xattr);
102 posix_acl_xattr_header *new;
103
104 if (unlikely(old_count <= new_count))
105 return old_size;
106
107 OBD_ALLOC(new, new_size);
108 if (unlikely(new == NULL))
109 return -ENOMEM;
110
111 memcpy(new, *header, new_size);
112 OBD_FREE(*header, old_size);
113 *header = new;
114 return new_size;
115}
116
117
118static int lustre_ext_acl_xattr_reduce_space(ext_acl_xattr_header **header,
119 int old_count)
120{
121 int ext_count = le32_to_cpu((*header)->a_count);
122 int ext_size = CFS_ACL_XATTR_SIZE(ext_count, ext_acl_xattr);
123 int old_size = CFS_ACL_XATTR_SIZE(old_count, ext_acl_xattr);
124 ext_acl_xattr_header *new;
125
126 if (unlikely(old_count <= ext_count))
127 return 0;
128
129 OBD_ALLOC(new, ext_size);
130 if (unlikely(new == NULL))
131 return -ENOMEM;
132
133 memcpy(new, *header, ext_size);
134 OBD_FREE(*header, old_size);
135 *header = new;
136 return 0;
137}
138
139
140
141
142ext_acl_xattr_header *
143lustre_posix_acl_xattr_2ext(posix_acl_xattr_header *header, int size)
144{
145 int count, i, esize;
146 ext_acl_xattr_header *new;
147 ENTRY;
148
149 if (unlikely(size < 0))
150 RETURN(ERR_PTR(-EINVAL));
151 else if (!size)
152 count = 0;
153 else
154 count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
155 esize = CFS_ACL_XATTR_SIZE(count, ext_acl_xattr);
156 OBD_ALLOC(new, esize);
157 if (unlikely(new == NULL))
158 RETURN(ERR_PTR(-ENOMEM));
159
160 new->a_count = cpu_to_le32(count);
161 for (i = 0; i < count; i++) {
162 new->a_entries[i].e_tag = header->a_entries[i].e_tag;
163 new->a_entries[i].e_perm = header->a_entries[i].e_perm;
164 new->a_entries[i].e_id = header->a_entries[i].e_id;
165 new->a_entries[i].e_stat = cpu_to_le32(ES_UNK);
166 }
167
168 RETURN(new);
169}
170EXPORT_SYMBOL(lustre_posix_acl_xattr_2ext);
171
172
173
174
175int lustre_posix_acl_xattr_filter(posix_acl_xattr_header *header, int size,
176 posix_acl_xattr_header **out)
177{
178 int count, i, j, rc = 0;
179 __u32 id;
180 posix_acl_xattr_header *new;
181 ENTRY;
182
183 if (unlikely(size < 0))
184 RETURN(-EINVAL);
185 else if (!size)
186 RETURN(0);
187
188 OBD_ALLOC(new, size);
189 if (unlikely(new == NULL))
190 RETURN(-ENOMEM);
191
192 new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
193 count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
194 for (i = 0, j = 0; i < count; i++) {
195 id = le32_to_cpu(header->a_entries[i].e_id);
196 switch (le16_to_cpu(header->a_entries[i].e_tag)) {
197 case ACL_USER_OBJ:
198 case ACL_GROUP_OBJ:
199 case ACL_MASK:
200 case ACL_OTHER:
201 if (id != ACL_UNDEFINED_ID)
202 GOTO(_out, rc = -EIO);
203
204 memcpy(&new->a_entries[j++], &header->a_entries[i],
205 sizeof(posix_acl_xattr_entry));
206 break;
207 case ACL_USER:
208 if (id != NOBODY_UID)
209 memcpy(&new->a_entries[j++],
210 &header->a_entries[i],
211 sizeof(posix_acl_xattr_entry));
212 break;
213 case ACL_GROUP:
214 if (id != NOBODY_GID)
215 memcpy(&new->a_entries[j++],
216 &header->a_entries[i],
217 sizeof(posix_acl_xattr_entry));
218 break;
219 default:
220 GOTO(_out, rc = -EIO);
221 }
222 }
223
224
225 rc = lustre_posix_acl_xattr_reduce_space(&new, count, j);
226 if (rc >= 0) {
227 size = rc;
228 *out = new;
229 rc = 0;
230 }
231 EXIT;
232
233_out:
234 if (rc) {
235 OBD_FREE(new, size);
236 size = rc;
237 }
238 return size;
239}
240EXPORT_SYMBOL(lustre_posix_acl_xattr_filter);
241
242
243
244
245void lustre_posix_acl_xattr_free(posix_acl_xattr_header *header, int size)
246{
247 OBD_FREE(header, size);
248}
249EXPORT_SYMBOL(lustre_posix_acl_xattr_free);
250
251
252
253
254void lustre_ext_acl_xattr_free(ext_acl_xattr_header *header)
255{
256 OBD_FREE(header, CFS_ACL_XATTR_SIZE(le32_to_cpu(header->a_count), \
257 ext_acl_xattr));
258}
259EXPORT_SYMBOL(lustre_ext_acl_xattr_free);
260
261static ext_acl_xattr_entry *
262lustre_ext_acl_xattr_search(ext_acl_xattr_header *header,
263 posix_acl_xattr_entry *entry, int *pos)
264{
265 int once, start, end, i, j, count = le32_to_cpu(header->a_count);
266
267 once = 0;
268 start = *pos;
269 end = count;
270
271again:
272 for (i = start; i < end; i++) {
273 if (header->a_entries[i].e_tag == entry->e_tag &&
274 header->a_entries[i].e_id == entry->e_id) {
275 j = i;
276 if (++i >= count)
277 i = 0;
278 *pos = i;
279 return &header->a_entries[j];
280 }
281 }
282
283 if (!once) {
284 once = 1;
285 start = 0;
286 end = *pos;
287 goto again;
288 }
289
290 return NULL;
291}
292
293
294
295
296int lustre_acl_xattr_merge2posix(posix_acl_xattr_header *posix_header, int size,
297 ext_acl_xattr_header *ext_header,
298 posix_acl_xattr_header **out)
299{
300 int posix_count, posix_size, i, j;
301 int ext_count = le32_to_cpu(ext_header->a_count), pos = 0, rc = 0;
302 posix_acl_xattr_entry pe = {ACL_MASK, 0, ACL_UNDEFINED_ID};
303 posix_acl_xattr_header *new;
304 ext_acl_xattr_entry *ee, ae;
305 ENTRY;
306
307 lustre_posix_acl_cpu_to_le(&pe, &pe);
308 ee = lustre_ext_acl_xattr_search(ext_header, &pe, &pos);
309 if (ee == NULL || le32_to_cpu(ee->e_stat) == ES_DEL) {
310
311 posix_count = 3;
312 posix_size = CFS_ACL_XATTR_SIZE(posix_count, posix_acl_xattr);
313 OBD_ALLOC(new, posix_size);
314 if (unlikely(new == NULL))
315 RETURN(-ENOMEM);
316
317 new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
318 for (i = 0, j = 0; i < ext_count; i++) {
319 lustre_ext_acl_le_to_cpu(&ae,
320 &ext_header->a_entries[i]);
321 switch (ae.e_tag) {
322 case ACL_USER_OBJ:
323 case ACL_GROUP_OBJ:
324 case ACL_OTHER:
325 if (ae.e_id != ACL_UNDEFINED_ID)
326 GOTO(_out, rc = -EIO);
327
328 if (ae.e_stat != ES_DEL) {
329 new->a_entries[j].e_tag =
330 ext_header->a_entries[i].e_tag;
331 new->a_entries[j].e_perm =
332 ext_header->a_entries[i].e_perm;
333 new->a_entries[j++].e_id =
334 ext_header->a_entries[i].e_id;
335 }
336 break;
337 case ACL_MASK:
338 case ACL_USER:
339 case ACL_GROUP:
340 if (ae.e_stat == ES_DEL)
341 break;
342 default:
343 GOTO(_out, rc = -EIO);
344 }
345 }
346 } else {
347
348
349 int ori_posix_count;
350
351 if (unlikely(size < 0))
352 RETURN(-EINVAL);
353 else if (!size)
354 ori_posix_count = 0;
355 else
356 ori_posix_count =
357 CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
358 posix_count = ori_posix_count + ext_count;
359 posix_size =
360 CFS_ACL_XATTR_SIZE(posix_count, posix_acl_xattr);
361 OBD_ALLOC(new, posix_size);
362 if (unlikely(new == NULL))
363 RETURN(-ENOMEM);
364
365 new->a_version = cpu_to_le32(CFS_ACL_XATTR_VERSION);
366
367
368 pos = 0;
369 for (i = 0, j = 0; i < ori_posix_count; i++) {
370 ee = lustre_ext_acl_xattr_search(ext_header,
371 &posix_header->a_entries[i], &pos);
372 if (ee == NULL)
373 memcpy(&new->a_entries[j++],
374 &posix_header->a_entries[i],
375 sizeof(posix_acl_xattr_entry));
376 }
377
378
379
380 for (i = 0; i < ext_count; i++) {
381 if (le16_to_cpu(ext_header->a_entries[i].e_stat) !=
382 ES_DEL) {
383 new->a_entries[j].e_tag =
384 ext_header->a_entries[i].e_tag;
385 new->a_entries[j].e_perm =
386 ext_header->a_entries[i].e_perm;
387 new->a_entries[j++].e_id =
388 ext_header->a_entries[i].e_id;
389 }
390 }
391 }
392
393
394 rc = lustre_posix_acl_xattr_reduce_space(&new, posix_count, j);
395 if (rc >= 0) {
396 posix_size = rc;
397 *out = new;
398 rc = 0;
399 }
400 EXIT;
401
402_out:
403 if (rc) {
404 OBD_FREE(new, posix_size);
405 posix_size = rc;
406 }
407 return posix_size;
408}
409EXPORT_SYMBOL(lustre_acl_xattr_merge2posix);
410
411
412
413
414ext_acl_xattr_header *
415lustre_acl_xattr_merge2ext(posix_acl_xattr_header *posix_header, int size,
416 ext_acl_xattr_header *ext_header)
417{
418 int ori_ext_count, posix_count, ext_count, ext_size;
419 int i, j, pos = 0, rc = 0;
420 posix_acl_xattr_entry pae;
421 ext_acl_xattr_header *new;
422 ext_acl_xattr_entry *ee, eae;
423 ENTRY;
424
425 if (unlikely(size < 0))
426 RETURN(ERR_PTR(-EINVAL));
427 else if (!size)
428 posix_count = 0;
429 else
430 posix_count = CFS_ACL_XATTR_COUNT(size, posix_acl_xattr);
431 ori_ext_count = le32_to_cpu(ext_header->a_count);
432 ext_count = posix_count + ori_ext_count;
433 ext_size = CFS_ACL_XATTR_SIZE(ext_count, ext_acl_xattr);
434
435 OBD_ALLOC(new, ext_size);
436 if (unlikely(new == NULL))
437 RETURN(ERR_PTR(-ENOMEM));
438
439 for (i = 0, j = 0; i < posix_count; i++) {
440 lustre_posix_acl_le_to_cpu(&pae, &posix_header->a_entries[i]);
441 switch (pae.e_tag) {
442 case ACL_USER_OBJ:
443 case ACL_GROUP_OBJ:
444 case ACL_MASK:
445 case ACL_OTHER:
446 if (pae.e_id != ACL_UNDEFINED_ID)
447 GOTO(out, rc = -EIO);
448 case ACL_USER:
449
450 if (pae.e_id == NOBODY_UID)
451 break;
452
453 new->a_entries[j].e_tag =
454 posix_header->a_entries[i].e_tag;
455 new->a_entries[j].e_perm =
456 posix_header->a_entries[i].e_perm;
457 new->a_entries[j].e_id =
458 posix_header->a_entries[i].e_id;
459 ee = lustre_ext_acl_xattr_search(ext_header,
460 &posix_header->a_entries[i], &pos);
461 if (ee) {
462 if (posix_header->a_entries[i].e_perm !=
463 ee->e_perm)
464
465 ee->e_stat =
466 new->a_entries[j++].e_stat =
467 cpu_to_le32(ES_MOD);
468 else
469
470 ee->e_stat =
471 new->a_entries[j++].e_stat =
472 cpu_to_le32(ES_UNC);
473 } else {
474
475 new->a_entries[j++].e_stat =
476 cpu_to_le32(ES_ADD);
477 }
478 break;
479 case ACL_GROUP:
480
481 if (pae.e_id == NOBODY_GID)
482 break;
483 new->a_entries[j].e_tag =
484 posix_header->a_entries[i].e_tag;
485 new->a_entries[j].e_perm =
486 posix_header->a_entries[i].e_perm;
487 new->a_entries[j].e_id =
488 posix_header->a_entries[i].e_id;
489 ee = lustre_ext_acl_xattr_search(ext_header,
490 &posix_header->a_entries[i], &pos);
491 if (ee) {
492 if (posix_header->a_entries[i].e_perm !=
493 ee->e_perm)
494
495 ee->e_stat =
496 new->a_entries[j++].e_stat =
497 cpu_to_le32(ES_MOD);
498 else
499
500 ee->e_stat =
501 new->a_entries[j++].e_stat =
502 cpu_to_le32(ES_UNC);
503 } else {
504
505 new->a_entries[j++].e_stat =
506 cpu_to_le32(ES_ADD);
507 }
508 break;
509 default:
510 GOTO(out, rc = -EIO);
511 }
512 }
513
514
515 for (i = 0; i < ori_ext_count; i++) {
516 lustre_ext_acl_le_to_cpu(&eae, &ext_header->a_entries[i]);
517 if (eae.e_stat == ES_UNK) {
518
519 if ((eae.e_tag == ACL_USER && eae.e_id == NOBODY_UID) ||
520 (eae.e_tag == ACL_GROUP && eae.e_id == NOBODY_GID))
521 continue;
522
523 new->a_entries[j].e_tag =
524 ext_header->a_entries[i].e_tag;
525 new->a_entries[j].e_perm =
526 ext_header->a_entries[i].e_perm;
527 new->a_entries[j].e_id = ext_header->a_entries[i].e_id;
528 new->a_entries[j++].e_stat = cpu_to_le32(ES_DEL);
529 }
530 }
531
532 new->a_count = cpu_to_le32(j);
533
534 rc = lustre_ext_acl_xattr_reduce_space(&new, ext_count);
535 EXIT;
536
537out:
538 if (rc) {
539 OBD_FREE(new, ext_size);
540 new = ERR_PTR(rc);
541 }
542 return new;
543}
544EXPORT_SYMBOL(lustre_acl_xattr_merge2ext);
545
546#endif
547