00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <linux/sched.h>
00010 #include <linux/smp_lock.h>
00011 #include <linux/module.h>
00012 #ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
00013 #include <linux/random.h>
00014 #endif
00015 #include <asm/uaccess.h>
00016 #include <rsbac/types.h>
00017 #include <rsbac/error.h>
00018 #include <rsbac/helpers.h>
00019 #include <rsbac/getname.h>
00020 #include <rsbac/debug.h>
00021 #include <rsbac/adf.h>
00022 #include <rsbac/aci_data_structures.h>
00023 #include <rsbac/proc_fs.h>
00024 #include <rsbac/rkmem.h>
00025 #include <rsbac/lists.h>
00026 #include <rsbac/gen_lists.h>
00027
00028
00029
00030
00031
00032 static struct rsbac_list_reg_head_t reg_head;
00033 static struct rsbac_list_lol_reg_head_t lol_reg_head;
00034 static rsbac_boolean_t list_initialized = FALSE;
00035
00036 static u_int rsbac_list_max_hashes = RSBAC_LIST_MIN_MAX_HASHES;
00037 static u_int rsbac_list_lol_max_hashes = RSBAC_LIST_MIN_MAX_HASHES;
00038
00039 #ifdef CONFIG_RSBAC_LIST_TRANS
00040 static struct rsbac_list_reg_item_t *ta_handle = NULL;
00041 static spinlock_t ta_lock = SPIN_LOCK_UNLOCKED;
00042 static rsbac_boolean_t ta_committing = FALSE;
00043 static rsbac_boolean_t ta_forgetting = FALSE;
00044 #ifndef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
00045 rsbac_list_ta_number_t ta_next = 1;
00046 #endif
00047 #endif
00048
00049 #ifdef CONFIG_RSBAC_LIST_TRANS
00050 static int do_forget(rsbac_list_ta_number_t ta_number);
00051 #endif
00052
00053 #ifdef CONFIG_RSBAC_AUTO_WRITE
00054 static rsbac_time_t next_rehash = 0;
00055 #endif
00056
00057
00058
00059
00060
00061 static inline struct rsbac_list_item_t *lookup_item_compare(
00062 struct rsbac_list_reg_item_t *list, void *desc)
00063 {
00064 struct rsbac_list_item_t *curr;
00065 u_int hash = 0;
00066
00067 if (!list || !desc || !list->compare)
00068 return NULL;
00069
00070 if(list->hash_function)
00071 hash = list->hash_function(desc, list->nr_hashes);
00072 curr = list->hashed[hash].curr;
00073 if (!curr) {
00074 curr = list->hashed[hash].head;
00075 if (!curr)
00076 return NULL;
00077 }
00078
00079
00080 if (list->compare(desc, &curr[1])) {
00081 if ((list->compare(desc, &curr[1]) > 0)) {
00082 curr = curr->next;
00083 while (curr && (list->compare(desc, &curr[1]) > 0)
00084 )
00085 curr = curr->next;
00086 } else {
00087 curr = curr->prev;
00088 while (curr && (list->compare(desc, &curr[1]) < 0)
00089 )
00090 curr = curr->prev;
00091 }
00092 if (curr) {
00093
00094 list->hashed[hash].curr = curr;
00095 if (!list->compare(desc, &curr[1]))
00096 return curr;
00097 }
00098
00099 return NULL;
00100 }
00101
00102 return curr;
00103 }
00104
00105 static inline struct rsbac_list_item_t *lookup_item_memcmp(struct
00106 rsbac_list_reg_item_t
00107 *list, void *desc)
00108 {
00109 struct rsbac_list_item_t *curr;
00110 u_int hash = 0;
00111
00112 if (!list || !desc)
00113 return NULL;
00114
00115 if(list->hash_function)
00116 hash = list->hash_function(desc, list->nr_hashes);
00117 curr = list->hashed[hash].curr;
00118 if (!curr) {
00119 curr = list->hashed[hash].head;
00120 if (!curr)
00121 return NULL;
00122 }
00123
00124
00125 if (memcmp(desc, &curr[1], list->info.desc_size)) {
00126 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
00127 curr = curr->next;
00128 while (curr
00129 && (memcmp(desc,
00130 &curr[1],
00131 list->info.desc_size) > 0)
00132 )
00133 curr = curr->next;
00134 } else {
00135 curr = curr->prev;
00136 while (curr
00137 && (memcmp(desc,
00138 &curr[1],
00139 list->info.desc_size) < 0)
00140 )
00141 curr = curr->prev;
00142 }
00143 if (curr) {
00144
00145 list->hashed[hash].curr = curr;
00146 if (!memcmp(desc, &curr[1], list->info.desc_size))
00147 return curr;
00148 }
00149
00150 return NULL;
00151 }
00152
00153 return curr;
00154 }
00155
00156 static struct rsbac_list_item_t *lookup_item(struct rsbac_list_reg_item_t
00157 *list, void *desc)
00158 {
00159 if (!list || !desc)
00160 return NULL;
00161
00162 if (list->compare)
00163 return lookup_item_compare(list, desc);
00164 else
00165 return lookup_item_memcmp(list, desc);
00166 }
00167
00168 #ifdef CONFIG_RSBAC_LIST_TRANS
00169 static inline struct rsbac_list_item_t *ta_lookup_item_compare(struct
00170 rsbac_list_reg_item_t
00171 *list, void *desc)
00172 {
00173 struct rsbac_list_item_t *curr;
00174 u_int hash = 0;
00175
00176 if (!list || !desc || !list->compare)
00177 return NULL;
00178
00179 if(list->hash_function)
00180 hash = list->hash_function(desc, list->nr_hashes);
00181 curr = list->hashed[hash].ta_curr;
00182 if (!curr) {
00183 curr = list->hashed[hash].ta_head;
00184 if (!curr)
00185 return NULL;
00186 }
00187
00188
00189 if (list->compare(desc, &curr[1])) {
00190 if ((list->compare(desc, &curr[1]) > 0)) {
00191 curr = curr->next;
00192 while (curr && (list->compare(desc, &curr[1]) > 0)
00193 )
00194 curr = curr->next;
00195 } else {
00196 curr = curr->prev;
00197 while (curr && (list->compare(desc, &curr[1]) < 0)
00198 )
00199 curr = curr->prev;
00200 }
00201 if (curr) {
00202
00203 list->hashed[hash].ta_curr = curr;
00204 if (!list->compare(desc, &curr[1]))
00205 return curr;
00206 }
00207
00208 return NULL;
00209 }
00210
00211 return curr;
00212 }
00213
00214 static inline struct rsbac_list_item_t *ta_lookup_item_memcmp(struct
00215 rsbac_list_reg_item_t
00216 *list, void *desc)
00217 {
00218 struct rsbac_list_item_t *curr;
00219 u_int hash = 0;
00220
00221 if (!list || !desc)
00222 return NULL;
00223
00224 if(list->hash_function)
00225 hash = list->hash_function(desc, list->nr_hashes);
00226 curr = list->hashed[hash].ta_curr;
00227 if (!curr) {
00228 curr = list->hashed[hash].ta_head;
00229 if (!curr)
00230 return NULL;
00231 }
00232
00233
00234 if (memcmp(desc, &curr[1], list->info.desc_size)) {
00235 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
00236 curr = curr->next;
00237 while (curr
00238 && (memcmp(desc,
00239 &curr[1],
00240 list->info.desc_size) > 0)
00241 )
00242 curr = curr->next;
00243 } else {
00244 curr = curr->prev;
00245 while (curr
00246 && (memcmp(desc,
00247 &curr[1],
00248 list->info.desc_size) < 0)
00249 )
00250 curr = curr->prev;
00251 }
00252 if (curr) {
00253
00254 list->hashed[hash].ta_curr = curr;
00255 if (!memcmp(desc, &curr[1], list->info.desc_size))
00256 return curr;
00257 }
00258
00259 return NULL;
00260 }
00261
00262 return curr;
00263 }
00264
00265 static struct rsbac_list_item_t *ta_lookup_item(rsbac_list_ta_number_t
00266 ta_number,
00267 struct
00268 rsbac_list_reg_item_t
00269 *list, void *desc)
00270 {
00271 u_int hash = 0;
00272
00273 if (!list || !desc)
00274 return NULL;
00275
00276 if(list->hash_function)
00277 hash = list->hash_function(desc, list->nr_hashes);
00278 if (!list->hashed[hash].ta_copied)
00279 return lookup_item(list, desc);
00280 if (list->hashed[hash].ta_copied != ta_number)
00281 return NULL;
00282
00283 if (list->compare)
00284 return ta_lookup_item_compare(list, desc);
00285 else
00286 return ta_lookup_item_memcmp(list, desc);
00287 }
00288 #endif
00289
00290 static inline struct rsbac_list_item_t *lookup_item_data_compare(struct
00291 rsbac_list_reg_item_t
00292 *list,
00293 void *data,
00294 rsbac_list_data_compare_function_t
00295 compare)
00296 {
00297 struct rsbac_list_item_t *curr;
00298 int i;
00299
00300 if (!list || !data || !compare)
00301 return NULL;
00302
00303 for(i=0; i<list->nr_hashes; i++) {
00304 curr = list->hashed[i].head;
00305
00306
00307 while (curr
00308 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00309 || compare((char *) curr + sizeof(*curr) +
00310 list->info.desc_size, data)
00311 )
00312 )
00313 curr = curr->next;
00314 if(curr)
00315 return curr;
00316 }
00317 return NULL;
00318 }
00319
00320 static inline struct rsbac_list_item_t *lookup_item_data_memcmp(struct
00321 rsbac_list_reg_item_t
00322 *list, void *data)
00323 {
00324 struct rsbac_list_item_t *curr;
00325 int i;
00326
00327 if (!list || !data)
00328 return NULL;
00329
00330 for(i=0; i<list->nr_hashes; i++) {
00331 curr = list->hashed[i].head;
00332
00333
00334 while (curr
00335 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00336 || memcmp(data,
00337 &curr[1] + list->info.desc_size,
00338 list->info.data_size)
00339 )
00340 )
00341 curr = curr->next;
00342 if(curr)
00343 return curr;
00344 }
00345 return NULL;
00346 }
00347
00348 static struct rsbac_list_item_t *lookup_item_data(struct
00349 rsbac_list_reg_item_t
00350 *list, void *data,
00351 rsbac_list_data_compare_function_t
00352 compare)
00353 {
00354 if (!list || !data)
00355 return NULL;
00356
00357 if (compare)
00358 return lookup_item_data_compare(list, data, compare);
00359 else
00360 return lookup_item_data_memcmp(list, data);
00361 }
00362
00363 #ifdef CONFIG_RSBAC_LIST_TRANS
00364 static inline struct rsbac_list_item_t *ta_lookup_item_data_compare(
00365 rsbac_list_ta_number_t ta_number,
00366 struct rsbac_list_reg_item_t *list,
00367 void *data,
00368 rsbac_list_data_compare_function_t compare)
00369 {
00370 struct rsbac_list_item_t *curr;
00371 int i;
00372
00373 if (!list || !data || !compare)
00374 return NULL;
00375
00376 for(i=0; i<list->nr_hashes; i++) {
00377 if (!list->hashed[i].ta_copied || list->hashed[i].ta_copied != ta_number)
00378 curr = list->hashed[i].head;
00379 else
00380 curr = list->hashed[i].ta_head;
00381
00382
00383 while (curr
00384 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00385 || compare((char *) curr + sizeof(*curr) +
00386 list->info.desc_size, data)
00387 )
00388 )
00389 curr = curr->next;
00390 if(curr)
00391 return curr;
00392 }
00393 return NULL;
00394 }
00395
00396 static inline struct rsbac_list_item_t *ta_lookup_item_data_memcmp(
00397 rsbac_list_ta_number_t ta_number,
00398 struct rsbac_list_reg_item_t *list,
00399 void *data)
00400 {
00401 struct rsbac_list_item_t *curr;
00402 int i;
00403
00404 if (!list || !data)
00405 return NULL;
00406
00407 for(i=0; i<list->nr_hashes; i++) {
00408 if (!list->hashed[i].ta_copied || list->hashed[i].ta_copied != ta_number)
00409 curr = list->hashed[i].head;
00410 else
00411 curr = list->hashed[i].ta_head;
00412
00413
00414 while (curr
00415 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00416 || memcmp(data,
00417 &curr[1] + list->info.desc_size,
00418 list->info.data_size)
00419 )
00420 )
00421 curr = curr->next;
00422 if(curr)
00423 return curr;
00424 }
00425 return NULL;
00426 }
00427
00428 static struct rsbac_list_item_t *ta_lookup_item_data(
00429 rsbac_list_ta_number_t ta_number,
00430 struct rsbac_list_reg_item_t *list,
00431 void *data,
00432 rsbac_list_data_compare_function_t compare)
00433 {
00434 if (!list || !data)
00435 return NULL;
00436
00437 if(!ta_number)
00438 return lookup_item_data(list, data, compare);
00439 if (compare)
00440 return ta_lookup_item_data_compare(ta_number, list, data, compare);
00441 else
00442 return ta_lookup_item_data_memcmp(ta_number, list, data);
00443 }
00444 #endif
00445
00446
00447
00448 static inline struct rsbac_list_item_t *lookup_lol_subitem_compare(struct
00449 rsbac_list_lol_reg_item_t
00450 *list,
00451 struct
00452 rsbac_list_lol_item_t
00453 *sublist,
00454 void *subdesc,
00455 rsbac_list_compare_function_t
00456 compare)
00457 {
00458 struct rsbac_list_item_t *curr;
00459
00460 if (!list || !sublist || !subdesc || !compare)
00461 return NULL;
00462
00463 curr = sublist->curr;
00464 if (!curr) {
00465 curr = sublist->head;
00466 if (!curr)
00467 return NULL;
00468 }
00469
00470
00471 if (compare(&curr[1], subdesc)) {
00472 if ((compare(&curr[1], subdesc) < 0)) {
00473 curr = curr->next;
00474 while (curr && (compare(&curr[1], subdesc) < 0)
00475 )
00476 curr = curr->next;
00477 } else {
00478 curr = curr->prev;
00479 while (curr && (compare(&curr[1], subdesc) > 0)
00480 )
00481 curr = curr->prev;
00482 }
00483 if (curr) {
00484
00485 sublist->curr = curr;
00486 if (!compare(&curr[1], subdesc))
00487 return curr;
00488 }
00489
00490 return NULL;
00491 }
00492
00493 return curr;
00494 }
00495
00496 static inline struct rsbac_list_item_t *lookup_lol_subitem_memcmp(struct
00497 rsbac_list_lol_reg_item_t
00498 *list,
00499 struct
00500 rsbac_list_lol_item_t
00501 *sublist,
00502 void *subdesc)
00503 {
00504 struct rsbac_list_item_t *curr;
00505
00506 if (!list || !sublist || !subdesc)
00507 return NULL;
00508
00509 curr = sublist->curr;
00510 if (!curr) {
00511 curr = sublist->head;
00512 if (!curr)
00513 return NULL;
00514 }
00515
00516
00517 if (memcmp(subdesc, &curr[1], list->info.subdesc_size)) {
00518 if (memcmp(subdesc, &curr[1], list->info.subdesc_size) > 0) {
00519 curr = curr->next;
00520 while (curr
00521 && (memcmp(subdesc,
00522 &curr[1],
00523 list->info.subdesc_size) > 0)
00524 )
00525 curr = curr->next;
00526 } else {
00527 curr = curr->prev;
00528 while (curr
00529 && (memcmp(subdesc,
00530 &curr[1],
00531 list->info.subdesc_size) < 0)
00532 )
00533 curr = curr->prev;
00534 }
00535 if (curr) {
00536
00537 sublist->curr = curr;
00538 if (!memcmp(subdesc,
00539 &curr[1], list->info.subdesc_size))
00540 return curr;
00541 }
00542
00543 return NULL;
00544 }
00545
00546 return curr;
00547 }
00548
00549 static struct rsbac_list_item_t *lookup_lol_subitem(struct
00550 rsbac_list_lol_reg_item_t
00551 *list,
00552 struct
00553 rsbac_list_lol_item_t
00554 *sublist,
00555 void *subdesc)
00556 {
00557 if (!list || !sublist || !subdesc)
00558 return NULL;
00559
00560 if (list->subcompare)
00561 return lookup_lol_subitem_compare(list, sublist, subdesc,
00562 list->subcompare);
00563 else
00564 return lookup_lol_subitem_memcmp(list, sublist, subdesc);
00565 }
00566
00567 static inline struct rsbac_list_item_t *lookup_lol_subitem_user_compare(struct
00568 rsbac_list_lol_reg_item_t
00569 *list,
00570 struct
00571 rsbac_list_lol_item_t
00572 *sublist,
00573 void
00574 *subdesc,
00575 rsbac_list_compare_function_t
00576 compare)
00577 {
00578 struct rsbac_list_item_t *curr;
00579
00580 if (!list || !sublist || !subdesc || !compare)
00581 return NULL;
00582
00583 curr = sublist->head;
00584
00585 while (curr) {
00586 if (!compare(&curr[1], subdesc))
00587 return curr;
00588 curr = curr->next;
00589 }
00590 return curr;
00591 }
00592
00593
00594
00595 static inline struct rsbac_list_lol_item_t *lookup_lol_item_compare(struct
00596 rsbac_list_lol_reg_item_t
00597 *list,
00598 void *desc)
00599 {
00600 struct rsbac_list_lol_item_t *curr;
00601 u_int hash = 0;
00602
00603 if (!list || !desc || !list->compare)
00604 return NULL;
00605
00606 if(list->hash_function)
00607 hash = list->hash_function(desc, list->nr_hashes);
00608 curr = list->hashed[hash].curr;
00609 if (!curr) {
00610 curr = list->hashed[hash].head;
00611 if (!curr)
00612 return NULL;
00613 }
00614
00615
00616 if (list->compare(desc, &curr[1])) {
00617 if ((list->compare(desc, &curr[1]) > 0)) {
00618 curr = curr->next;
00619 while (curr && (list->compare(desc, &curr[1]) > 0)
00620 )
00621 curr = curr->next;
00622 } else {
00623 curr = curr->prev;
00624 while (curr && (list->compare(desc, &curr[1]) < 0)
00625 )
00626 curr = curr->prev;
00627 }
00628 if (curr) {
00629
00630 list->hashed[hash].curr = curr;
00631 if (!list->compare(desc, &curr[1]))
00632 return curr;
00633 }
00634
00635 return NULL;
00636 }
00637
00638 return curr;
00639 }
00640
00641 static inline struct rsbac_list_lol_item_t *lookup_lol_item_memcmp(struct
00642 rsbac_list_lol_reg_item_t
00643 *list,
00644 void *desc)
00645 {
00646 struct rsbac_list_lol_item_t *curr;
00647 u_int hash = 0;
00648
00649 if (!list || !desc)
00650 return NULL;
00651
00652 if(list->hash_function)
00653 hash = list->hash_function(desc, list->nr_hashes);
00654 curr = list->hashed[hash].curr;
00655 if (!curr) {
00656 curr = list->hashed[hash].head;
00657 if (!curr)
00658 return NULL;
00659 }
00660
00661
00662 if (memcmp(desc, &curr[1], list->info.desc_size)) {
00663 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
00664 curr = curr->next;
00665 while (curr
00666 && (memcmp(desc,
00667 &curr[1],
00668 list->info.desc_size) > 0)
00669 )
00670 curr = curr->next;
00671 } else {
00672 curr = curr->prev;
00673 while (curr
00674 && (memcmp(desc,
00675 &curr[1],
00676 list->info.desc_size) < 0)
00677 )
00678 curr = curr->prev;
00679 }
00680 if (curr) {
00681
00682 list->hashed[hash].curr = curr;
00683 if (!memcmp(desc, &curr[1], list->info.desc_size))
00684 return curr;
00685 }
00686
00687 return NULL;
00688 }
00689
00690 return curr;
00691 }
00692
00693 static struct rsbac_list_lol_item_t *lookup_lol_item(struct
00694 rsbac_list_lol_reg_item_t
00695 *list, void *desc)
00696 {
00697 if (!list || !desc)
00698 return NULL;
00699
00700 if (list->compare)
00701 return lookup_lol_item_compare(list, desc);
00702 else
00703 return lookup_lol_item_memcmp(list, desc);
00704 }
00705
00706 #ifdef CONFIG_RSBAC_LIST_TRANS
00707 static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_compare(struct
00708 rsbac_list_lol_reg_item_t
00709 *list,
00710 void *desc)
00711 {
00712 struct rsbac_list_lol_item_t *curr;
00713 u_int hash = 0;
00714
00715 if (!list || !desc || !list->compare)
00716 return NULL;
00717
00718 if(list->hash_function)
00719 hash = list->hash_function(desc, list->nr_hashes);
00720 curr = list->hashed[hash].ta_curr;
00721 if (!curr) {
00722 curr = list->hashed[hash].ta_head;
00723 if (!curr)
00724 return NULL;
00725 }
00726
00727
00728 if (list->compare(desc, &curr[1])) {
00729 if ((list->compare(desc, &curr[1]) > 0)) {
00730 curr = curr->next;
00731 while (curr && (list->compare(desc, &curr[1]) > 0)
00732 )
00733 curr = curr->next;
00734 } else {
00735 curr = curr->prev;
00736 while (curr && (list->compare(desc, &curr[1]) < 0)
00737 )
00738 curr = curr->prev;
00739 }
00740 if (curr) {
00741
00742 list->hashed[hash].ta_curr = curr;
00743 if (!list->compare(desc, &curr[1]))
00744 return curr;
00745 }
00746
00747 return NULL;
00748 }
00749
00750 return curr;
00751 }
00752
00753 static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_memcmp(struct
00754 rsbac_list_lol_reg_item_t
00755 *list,
00756 void *desc)
00757 {
00758 struct rsbac_list_lol_item_t *curr;
00759 u_int hash = 0;
00760
00761 if (!list || !desc)
00762 return NULL;
00763
00764 if(list->hash_function)
00765 hash = list->hash_function(desc, list->nr_hashes);
00766 curr = list->hashed[hash].ta_curr;
00767 if (!curr) {
00768 curr = list->hashed[hash].ta_head;
00769 if (!curr)
00770 return NULL;
00771 }
00772
00773
00774 if (memcmp(desc, &curr[1], list->info.desc_size)) {
00775 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
00776 curr = curr->next;
00777 while (curr
00778 && (memcmp(desc,
00779 &curr[1],
00780 list->info.desc_size) > 0)
00781 )
00782 curr = curr->next;
00783 } else {
00784 curr = curr->prev;
00785 while (curr
00786 && (memcmp(desc,
00787 &curr[1],
00788 list->info.desc_size) < 0)
00789 )
00790 curr = curr->prev;
00791 }
00792 if (curr) {
00793
00794 list->hashed[hash].ta_curr = curr;
00795 if (!memcmp(desc, &curr[1], list->info.desc_size))
00796 return curr;
00797 }
00798
00799 return NULL;
00800 }
00801
00802 return curr;
00803 }
00804
00805 static struct rsbac_list_lol_item_t
00806 *ta_lookup_lol_item(rsbac_list_ta_number_t ta_number,
00807 struct rsbac_list_lol_reg_item_t *list, void *desc)
00808 {
00809 u_int hash = 0;
00810
00811 if (!list || !desc)
00812 return NULL;
00813
00814 if(list->hash_function)
00815 hash = list->hash_function(desc, list->nr_hashes);
00816 if (!list->hashed[hash].ta_copied)
00817 return lookup_lol_item(list, desc);
00818 if (list->hashed[hash].ta_copied != ta_number)
00819 return NULL;
00820
00821 if (list->compare)
00822 return ta_lookup_lol_item_compare(list, desc);
00823 else
00824 return ta_lookup_lol_item_memcmp(list, desc);
00825 }
00826 #endif
00827
00828 static inline struct rsbac_list_lol_item_t *lookup_lol_item_data_compare(
00829 struct rsbac_list_lol_reg_item_t *list,
00830 void *data,
00831 rsbac_list_data_compare_function_t compare)
00832 {
00833 struct rsbac_list_lol_item_t *curr;
00834 int i;
00835
00836 if (!list || !data || !compare)
00837 return NULL;
00838
00839 for(i=0; i<list->nr_hashes; i++) {
00840 curr = list->hashed[i].head;
00841
00842
00843 while (curr
00844 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00845 || compare((char *) curr + sizeof(*curr) +
00846 list->info.desc_size, data)
00847 )
00848 )
00849 curr = curr->next;
00850 if(curr)
00851 return curr;
00852 }
00853 return NULL;
00854 }
00855
00856 static inline struct rsbac_list_lol_item_t *lookup_lol_item_data_memcmp(
00857 struct rsbac_list_lol_reg_item_t *list,
00858 void *data)
00859 {
00860 struct rsbac_list_lol_item_t *curr;
00861 int i;
00862
00863 if (!list || !data)
00864 return NULL;
00865
00866 for(i=0; i<list->nr_hashes; i++) {
00867 curr = list->hashed[i].head;
00868
00869
00870 while (curr
00871 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00872 || memcmp(data,
00873 &curr[1] + list->info.desc_size,
00874 list->info.data_size)
00875 )
00876 )
00877 curr = curr->next;
00878 if(curr)
00879 return curr;
00880 }
00881 return NULL;
00882 }
00883
00884 static struct rsbac_list_lol_item_t *lookup_lol_item_data(struct
00885 rsbac_list_lol_reg_item_t
00886 *list,
00887 void *data,
00888 rsbac_list_data_compare_function_t
00889 compare)
00890 {
00891 if (!list || !data)
00892 return NULL;
00893
00894 if (compare)
00895 return lookup_lol_item_data_compare(list, data, compare);
00896 else
00897 return lookup_lol_item_data_memcmp(list, data);
00898 }
00899
00900 #ifdef CONFIG_RSBAC_LIST_TRANS
00901 static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_data_compare(
00902 rsbac_list_ta_number_t ta_number,
00903 struct rsbac_list_lol_reg_item_t *list,
00904 void *data,
00905 rsbac_list_data_compare_function_t compare)
00906 {
00907 struct rsbac_list_lol_item_t *curr;
00908 int i;
00909
00910 if (!list || !data || !compare)
00911 return NULL;
00912
00913 for(i=0; i<list->nr_hashes; i++) {
00914 if (!list->hashed[i].ta_copied || list->hashed[i].ta_copied != ta_number)
00915 curr = list->hashed[i].head;
00916 else
00917 curr = list->hashed[i].ta_head;
00918
00919
00920 while (curr
00921 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00922 || compare((char *) curr + sizeof(*curr) +
00923 list->info.desc_size, data)
00924 )
00925 )
00926 curr = curr->next;
00927 if(curr)
00928 return curr;
00929 }
00930 return NULL;
00931 }
00932
00933 static inline struct rsbac_list_lol_item_t *ta_lookup_lol_item_data_memcmp(
00934 rsbac_list_ta_number_t ta_number,
00935 struct rsbac_list_lol_reg_item_t *list,
00936 void *data)
00937 {
00938 struct rsbac_list_lol_item_t *curr;
00939 int i;
00940
00941 if (!list || !data)
00942 return NULL;
00943
00944 for(i=0; i<list->nr_hashes; i++) {
00945 if (!list->hashed[i].ta_copied || list->hashed[i].ta_copied != ta_number)
00946 curr = list->hashed[i].head;
00947 else
00948 curr = list->hashed[i].ta_head;
00949
00950
00951 while (curr
00952 && ((curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00953 || memcmp(data,
00954 &curr[1] + list->info.desc_size,
00955 list->info.data_size)
00956 )
00957 )
00958 curr = curr->next;
00959 if(curr)
00960 return curr;
00961 }
00962 return NULL;
00963 }
00964
00965 static struct rsbac_list_lol_item_t
00966 *ta_lookup_lol_item_data(rsbac_list_ta_number_t ta_number,
00967 struct rsbac_list_lol_reg_item_t *list,
00968 void *data,
00969 rsbac_list_data_compare_function_t compare)
00970 {
00971 if (!list || !data)
00972 return NULL;
00973
00974 if(!ta_number)
00975 return lookup_lol_item_data(list, data, compare);
00976 if (compare)
00977 return ta_lookup_lol_item_data_compare(ta_number, list, data,
00978 compare);
00979 else
00980 return ta_lookup_lol_item_data_memcmp(ta_number, list, data);
00981 }
00982 #endif
00983
00984
00985
00986 static struct rsbac_list_reg_item_t *lookup_reg(struct
00987 rsbac_list_reg_item_t
00988 *handle)
00989 {
00990 struct rsbac_list_reg_item_t *curr = reg_head.curr;
00991
00992 if (!handle)
00993 return NULL;
00994
00995 if (curr != handle) {
00996 curr = reg_head.head;
00997 while (curr && curr != handle)
00998 curr = curr->next;
00999 if (curr)
01000 reg_head.curr = curr;
01001 else
01002 rsbac_pr_debug(lists,
01003 "Lookup of unknown list handle %p\n",
01004 handle);
01005 }
01006
01007 return curr;
01008 }
01009
01010 static struct rsbac_list_reg_item_t *lookup_reg_name(char *name,
01011 kdev_t device)
01012 {
01013 struct rsbac_list_reg_item_t *curr = reg_head.curr;
01014
01015 if (!name)
01016 return NULL;
01017
01018 if (!curr || (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01019 || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
01020 || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
01021 )
01022 ) {
01023 curr = reg_head.head;
01024 while (curr
01025 &&
01026 (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01027 || (RSBAC_MAJOR(curr->device) !=
01028 RSBAC_MAJOR(device))
01029 || (RSBAC_MINOR(curr->device) !=
01030 RSBAC_MINOR(device))
01031 )
01032 )
01033 curr = curr->next;
01034 if (curr)
01035 reg_head.curr = curr;
01036 else
01037 rsbac_pr_debug(lists, "Lookup of unknown list name %s "
01038 "on device %02u:%02u\n", name,
01039 RSBAC_MAJOR(device),
01040 RSBAC_MINOR(device));
01041 }
01042
01043 return curr;
01044 }
01045
01046
01047
01048 static struct rsbac_list_lol_reg_item_t *lookup_lol_reg(struct
01049 rsbac_list_lol_reg_item_t
01050 *handle)
01051 {
01052 struct rsbac_list_lol_reg_item_t *curr = lol_reg_head.curr;
01053
01054 if (!handle)
01055 return NULL;
01056
01057 if (curr != handle) {
01058 curr = lol_reg_head.head;
01059 while (curr && curr != handle)
01060 curr = curr->next;
01061 if (curr)
01062 lol_reg_head.curr = curr;
01063 else
01064 rsbac_pr_debug(lists, "Lookup of unknown list handle %p\n",
01065 handle);
01066 }
01067
01068 return curr;
01069 }
01070
01071 static struct rsbac_list_lol_reg_item_t *lookup_lol_reg_name(char *name,
01072 kdev_t device)
01073 {
01074 struct rsbac_list_lol_reg_item_t *curr = lol_reg_head.curr;
01075
01076 if (!name)
01077 return NULL;
01078
01079 if (!curr || (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01080 || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
01081 || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
01082 )
01083 ) {
01084 curr = lol_reg_head.head;
01085 while (curr
01086 &&
01087 (strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01088 || (RSBAC_MAJOR(curr->device) !=
01089 RSBAC_MAJOR(device))
01090 || (RSBAC_MINOR(curr->device) !=
01091 RSBAC_MINOR(device))
01092 )
01093 )
01094 curr = curr->next;
01095 if (curr)
01096 lol_reg_head.curr = curr;
01097 else
01098 rsbac_pr_debug(lists, "Lookup of unknown list name %s "
01099 "on device %02u:%02u\n", name,
01100 RSBAC_MAJOR(device),
01101 RSBAC_MINOR(device));
01102 }
01103
01104 return curr;
01105 }
01106
01107
01108
01109
01110 static inline struct rsbac_list_item_t *insert_item_compare(struct
01111 rsbac_list_reg_item_t
01112 *list, void *desc,
01113 struct
01114 rsbac_list_item_t
01115 *new_item_p)
01116 {
01117 struct rsbac_list_item_t *curr;
01118 u_int hash = 0;
01119
01120 if(list->hash_function)
01121 hash = list->hash_function(desc, list->nr_hashes);
01122 curr = list->hashed[hash].curr;
01123 if (!curr)
01124 curr = list->hashed[hash].head;
01125 if ((list->compare(desc, &curr[1]) > 0)) {
01126 curr = curr->next;
01127 while (curr && (list->compare(desc, &curr[1]) > 0)
01128 )
01129 curr = curr->next;
01130 if (curr) {
01131
01132 new_item_p->prev = curr->prev;
01133 new_item_p->next = curr;
01134 curr->prev->next = new_item_p;
01135 curr->prev = new_item_p;
01136 } else {
01137
01138 new_item_p->prev = list->hashed[hash].tail;
01139 new_item_p->next = NULL;
01140 list->hashed[hash].tail->next = new_item_p;
01141 list->hashed[hash].tail = new_item_p;
01142 }
01143 } else {
01144 curr = curr->prev;
01145 while (curr && (list->compare(desc, &curr[1]) < 0)
01146 )
01147 curr = curr->prev;
01148 if (curr) {
01149
01150 new_item_p->prev = curr;
01151 new_item_p->next = curr->next;
01152 curr->next->prev = new_item_p;
01153 curr->next = new_item_p;
01154 } else {
01155
01156 new_item_p->prev = NULL;
01157 new_item_p->next = list->hashed[hash].head;
01158 list->hashed[hash].head->prev = new_item_p;
01159 list->hashed[hash].head = new_item_p;
01160 }
01161 }
01162 list->hashed[hash].count++;
01163 list->hashed[hash].curr = new_item_p;
01164 return new_item_p;
01165 }
01166
01167 static inline struct rsbac_list_item_t *insert_item_memcmp(struct
01168 rsbac_list_reg_item_t
01169 *list, void *desc,
01170 struct
01171 rsbac_list_item_t
01172 *new_item_p)
01173 {
01174 struct rsbac_list_item_t *curr;
01175 u_int hash = 0;
01176
01177 if(list->hash_function)
01178 hash = list->hash_function(desc, list->nr_hashes);
01179 curr = list->hashed[hash].curr;
01180 if (!curr)
01181 curr = list->hashed[hash].head;
01182 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
01183 curr = curr->next;
01184 while (curr
01185 && (memcmp(desc,
01186 &curr[1], list->info.desc_size) > 0)
01187 )
01188 curr = curr->next;
01189 if (curr) {
01190
01191 new_item_p->prev = curr->prev;
01192 new_item_p->next = curr;
01193 curr->prev->next = new_item_p;
01194 curr->prev = new_item_p;
01195 } else {
01196
01197 new_item_p->prev = list->hashed[hash].tail;
01198 new_item_p->next = NULL;
01199 list->hashed[hash].tail->next = new_item_p;
01200 list->hashed[hash].tail = new_item_p;
01201 }
01202 } else {
01203 curr = curr->prev;
01204 while (curr
01205 && (memcmp(desc,
01206 &curr[1], list->info.desc_size) < 0)
01207 )
01208 curr = curr->prev;
01209 if (curr) {
01210
01211 new_item_p->prev = curr;
01212 new_item_p->next = curr->next;
01213 curr->next->prev = new_item_p;
01214 curr->next = new_item_p;
01215 } else {
01216
01217 new_item_p->prev = NULL;
01218 new_item_p->next = list->hashed[hash].head;
01219 list->hashed[hash].head->prev = new_item_p;
01220 list->hashed[hash].head = new_item_p;
01221 }
01222 }
01223 list->hashed[hash].count++;
01224 list->hashed[hash].curr = new_item_p;
01225 return new_item_p;
01226 }
01227
01228 static struct rsbac_list_item_t *add_item(struct rsbac_list_reg_item_t
01229 *list, rsbac_time_t max_age,
01230 void *desc, void *data)
01231 {
01232 struct rsbac_list_item_t *new_item_p = NULL;
01233 u_int hash = 0;
01234
01235 if (!list || !desc)
01236 return NULL;
01237
01238 if (!list || !desc)
01239 return NULL;
01240 if (list->info.data_size && !data)
01241 return NULL;
01242
01243 if (!
01244 (new_item_p =
01245 rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size +
01246 list->info.data_size)))
01247 return (NULL);
01248 new_item_p->max_age = max_age;
01249
01250 memcpy(&new_item_p[1], desc, list->info.desc_size);
01251
01252
01253 if (data && list->info.data_size)
01254 memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
01255 list->info.desc_size, data, list->info.data_size);
01256
01257 if(list->hash_function)
01258 hash = list->hash_function(desc, list->nr_hashes);
01259 if (!list->hashed[hash].head) {
01260 list->hashed[hash].head = new_item_p;
01261 list->hashed[hash].tail = new_item_p;
01262 list->hashed[hash].curr = new_item_p;
01263 list->hashed[hash].count = 1;
01264 new_item_p->prev = NULL;
01265 new_item_p->next = NULL;
01266 return new_item_p;
01267 }
01268 if(list->hashed[hash].count >= list->max_items_per_hash) {
01269 rsbac_kfree(new_item_p);
01270 if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
01271 rsbac_printk(KERN_WARNING "add_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
01272 list->name,
01273 hash,
01274 RSBAC_MAJOR(list->device),
01275 RSBAC_MINOR(list->device),
01276 list->max_items_per_hash);
01277 return NULL;
01278 }
01279 if (list->compare)
01280 return insert_item_compare(list, desc, new_item_p);
01281 else
01282 return insert_item_memcmp(list, desc, new_item_p);
01283 }
01284
01285 #ifdef CONFIG_RSBAC_LIST_TRANS
01286 static void ta_remove_all_items(struct rsbac_list_reg_item_t *list, u_int hash);
01287
01288 static int ta_copy(rsbac_list_ta_number_t ta_number,
01289 struct rsbac_list_reg_item_t *list,
01290 u_int hash)
01291 {
01292 struct rsbac_list_item_t *curr;
01293 struct rsbac_list_item_t *new_item_p;
01294 u_int item_size = sizeof(*new_item_p)
01295 + list->info.desc_size + list->info.data_size;
01296
01297 curr = list->hashed[hash].head;
01298 if (curr) {
01299 if (!(new_item_p = rsbac_kmalloc(item_size))) {
01300 ta_remove_all_items(list, hash);
01301 return (-RSBAC_ENOMEM);
01302 }
01303 memcpy(new_item_p, curr, item_size);
01304 new_item_p->prev = NULL;
01305 new_item_p->next = NULL;
01306 list->hashed[hash].ta_head = new_item_p;
01307 list->hashed[hash].ta_tail = new_item_p;
01308 list->hashed[hash].ta_curr = new_item_p;
01309 list->hashed[hash].ta_count = 1;
01310 curr = curr->next;
01311 } else {
01312 list->hashed[hash].ta_head = NULL;
01313 list->hashed[hash].ta_tail = NULL;
01314 list->hashed[hash].ta_curr = NULL;
01315 list->hashed[hash].ta_count = 0;
01316 list->hashed[hash].ta_copied = ta_number;
01317 return 0;
01318 }
01319 while (curr) {
01320 if (!(new_item_p = rsbac_kmalloc(item_size))) {
01321 ta_remove_all_items(list, hash);
01322 return (-RSBAC_ENOMEM);
01323 }
01324 memcpy(new_item_p, curr, item_size);
01325 new_item_p->prev = list->hashed[hash].ta_tail;
01326 new_item_p->next = NULL;
01327 list->hashed[hash].ta_tail->next = new_item_p;
01328 list->hashed[hash].ta_tail = new_item_p;
01329 list->hashed[hash].ta_count++;
01330 curr = curr->next;
01331 }
01332 list->hashed[hash].ta_copied = ta_number;
01333 return 0;
01334 }
01335
01336 static void ta_remove_all_lol_items(struct rsbac_list_lol_reg_item_t *list,
01337 u_int hash);
01338
01339 static int ta_lol_copy(rsbac_list_ta_number_t ta_number,
01340 struct rsbac_list_lol_reg_item_t *list,
01341 u_int hash)
01342 {
01343 struct rsbac_list_lol_item_t *curr;
01344 struct rsbac_list_lol_item_t *new_item_p;
01345 struct rsbac_list_item_t *sub_curr;
01346 struct rsbac_list_item_t *new_subitem_p;
01347 u_int item_size = sizeof(*new_item_p)
01348 + list->info.desc_size + list->info.data_size;
01349 u_int subitem_size = sizeof(*new_subitem_p)
01350 + list->info.subdesc_size + list->info.subdata_size;
01351
01352 list->hashed[hash].ta_head = NULL;
01353 list->hashed[hash].ta_tail = NULL;
01354 list->hashed[hash].ta_curr = NULL;
01355 list->hashed[hash].ta_count = 0;
01356
01357 curr = list->hashed[hash].head;
01358 while (curr) {
01359 if (!(new_item_p = rsbac_kmalloc(item_size))) {
01360 ta_remove_all_lol_items(list, hash);
01361 return (-RSBAC_ENOMEM);
01362 }
01363 memcpy(new_item_p, curr, item_size);
01364 new_item_p->head = NULL;
01365 new_item_p->tail = NULL;
01366 new_item_p->curr = NULL;
01367 new_item_p->count = 0;
01368 new_item_p->prev = NULL;
01369 new_item_p->next = NULL;
01370 sub_curr = curr->head;
01371 while (sub_curr) {
01372 if (!(new_subitem_p = rsbac_kmalloc(subitem_size))) {
01373 ta_remove_all_lol_items(list, hash);
01374 rsbac_kfree(new_item_p);
01375 return (-RSBAC_ENOMEM);
01376 }
01377 memcpy(new_subitem_p, sub_curr, subitem_size);
01378 new_subitem_p->prev = NULL;
01379 new_subitem_p->next = NULL;
01380 if (new_item_p->tail) {
01381 new_subitem_p->prev = new_item_p->tail;
01382 new_item_p->tail->next = new_subitem_p;
01383 new_item_p->tail = new_subitem_p;
01384 new_item_p->count++;
01385 } else {
01386 new_item_p->head = new_subitem_p;
01387 new_item_p->tail = new_subitem_p;
01388 new_item_p->count = 1;
01389 }
01390 sub_curr = sub_curr->next;
01391 }
01392 if (list->hashed[hash].ta_tail) {
01393 new_item_p->prev = list->hashed[hash].ta_tail;
01394 list->hashed[hash].ta_tail->next = new_item_p;
01395 list->hashed[hash].ta_tail = new_item_p;
01396 list->hashed[hash].ta_count++;
01397 } else {
01398 list->hashed[hash].ta_head = new_item_p;
01399 list->hashed[hash].ta_tail = new_item_p;
01400 list->hashed[hash].ta_curr = new_item_p;
01401 list->hashed[hash].ta_count = 1;
01402 }
01403 curr = curr->next;
01404 }
01405 list->hashed[hash].ta_copied = ta_number;
01406 return 0;
01407 }
01408
01409 static inline struct rsbac_list_item_t *ta_insert_item_compare(struct
01410 rsbac_list_reg_item_t
01411 *list, void *desc,
01412 struct
01413 rsbac_list_item_t
01414 *new_item_p)
01415 {
01416 struct rsbac_list_item_t *curr;
01417 u_int hash = 0;
01418
01419 if(list->hash_function)
01420 hash = list->hash_function(desc, list->nr_hashes);
01421 curr = list->hashed[hash].ta_curr;
01422 if (!curr)
01423 curr = list->hashed[hash].ta_head;
01424 if ((list->compare(desc, &curr[1]) > 0)) {
01425 curr = curr->next;
01426 while (curr && (list->compare(desc, &curr[1]) > 0)
01427 )
01428 curr = curr->next;
01429 if (curr) {
01430
01431 new_item_p->prev = curr->prev;
01432 new_item_p->next = curr;
01433 curr->prev->next = new_item_p;
01434 curr->prev = new_item_p;
01435 } else {
01436
01437 new_item_p->prev = list->hashed[hash].ta_tail;
01438 new_item_p->next = NULL;
01439 list->hashed[hash].ta_tail->next = new_item_p;
01440 list->hashed[hash].ta_tail = new_item_p;
01441 }
01442 } else {
01443 curr = curr->prev;
01444 while (curr && (list->compare(desc, &curr[1]) < 0)
01445 )
01446 curr = curr->prev;
01447 if (curr) {
01448
01449 new_item_p->prev = curr;
01450 new_item_p->next = curr->next;
01451 curr->next->prev = new_item_p;
01452 curr->next = new_item_p;
01453 } else {
01454
01455 new_item_p->prev = NULL;
01456 new_item_p->next = list->hashed[hash].ta_head;
01457 list->hashed[hash].ta_head->prev = new_item_p;
01458 list->hashed[hash].ta_head = new_item_p;
01459 }
01460 }
01461 list->hashed[hash].ta_count++;
01462 list->hashed[hash].ta_curr = new_item_p;
01463 return new_item_p;
01464 }
01465
01466 static inline struct rsbac_list_item_t *ta_insert_item_memcmp(struct
01467 rsbac_list_reg_item_t
01468 *list, void *desc,
01469 struct
01470 rsbac_list_item_t
01471 *new_item_p)
01472 {
01473 struct rsbac_list_item_t *curr;
01474 u_int hash = 0;
01475
01476 if(list->hash_function)
01477 hash = list->hash_function(desc, list->nr_hashes);
01478 curr = list->hashed[hash].ta_curr;
01479 if (!curr)
01480 curr = list->hashed[hash].ta_head;
01481 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
01482 curr = curr->next;
01483 while (curr
01484 && (memcmp(desc,
01485 &curr[1], list->info.desc_size) > 0)
01486 )
01487 curr = curr->next;
01488 if (curr) {
01489
01490 new_item_p->prev = curr->prev;
01491 new_item_p->next = curr;
01492 curr->prev->next = new_item_p;
01493 curr->prev = new_item_p;
01494 } else {
01495
01496 new_item_p->prev = list->hashed[hash].ta_tail;
01497 new_item_p->next = NULL;
01498 list->hashed[hash].ta_tail->next = new_item_p;
01499 list->hashed[hash].ta_tail = new_item_p;
01500 }
01501 } else {
01502 curr = curr->prev;
01503 while (curr
01504 && (memcmp(desc,
01505 &curr[1], list->info.desc_size) < 0)
01506 )
01507 curr = curr->prev;
01508 if (curr) {
01509
01510 new_item_p->prev = curr;
01511 new_item_p->next = curr->next;
01512 curr->next->prev = new_item_p;
01513 curr->next = new_item_p;
01514 } else {
01515
01516 new_item_p->prev = NULL;
01517 new_item_p->next = list->hashed[hash].ta_head;
01518 list->hashed[hash].ta_head->prev = new_item_p;
01519 list->hashed[hash].ta_head = new_item_p;
01520 }
01521 }
01522 list->hashed[hash].ta_count++;
01523 list->hashed[hash].ta_curr = new_item_p;
01524 return new_item_p;
01525 }
01526
01527 static struct rsbac_list_item_t *ta_add_item(rsbac_list_ta_number_t
01528 ta_number,
01529 struct rsbac_list_reg_item_t
01530 *list, rsbac_time_t max_age,
01531 void *desc, void *data)
01532 {
01533 struct rsbac_list_item_t *new_item_p = NULL;
01534 u_int hash = 0;
01535
01536 if (!list || !desc)
01537 return NULL;
01538
01539 if (!list || !desc)
01540 return NULL;
01541 if (list->info.data_size && !data)
01542 return NULL;
01543 if (!ta_number)
01544 return add_item(list, max_age, desc, data);
01545
01546 if (!
01547 (new_item_p =
01548 rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size +
01549 list->info.data_size)))
01550 return (NULL);
01551 new_item_p->max_age = max_age;
01552
01553 memcpy(&new_item_p[1], desc, list->info.desc_size);
01554
01555
01556 if (data && list->info.data_size)
01557 memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
01558 list->info.desc_size, data, list->info.data_size);
01559
01560 if(list->hash_function)
01561 hash = list->hash_function(desc, list->nr_hashes);
01562 if (!list->hashed[hash].ta_copied) {
01563 if (ta_copy(ta_number, list, hash)) {
01564 rsbac_kfree(new_item_p);
01565 return NULL;
01566 }
01567 } else {
01568 if (list->hashed[hash].ta_copied != ta_number) {
01569 rsbac_kfree(new_item_p);
01570 return NULL;
01571 }
01572 }
01573
01574 if (!list->hashed[hash].ta_head) {
01575 list->hashed[hash].ta_head = new_item_p;
01576 list->hashed[hash].ta_tail = new_item_p;
01577 list->hashed[hash].ta_curr = new_item_p;
01578 list->hashed[hash].ta_count = 1;
01579 new_item_p->prev = NULL;
01580 new_item_p->next = NULL;
01581 return new_item_p;
01582 }
01583 if (list->hashed[hash].ta_count >= list->max_items_per_hash) {
01584 rsbac_kfree(new_item_p);
01585 if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
01586 rsbac_printk(KERN_WARNING "ta_add_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
01587 list->name,
01588 hash,
01589 RSBAC_MAJOR(list->device),
01590 RSBAC_MINOR(list->device),
01591 list->max_items_per_hash);
01592 return NULL;
01593 }
01594 if (list->compare)
01595 return ta_insert_item_compare(list, desc, new_item_p);
01596 else
01597 return ta_insert_item_memcmp(list, desc, new_item_p);
01598 }
01599 #endif
01600
01601
01602 static inline struct rsbac_list_item_t *insert_lol_subitem_compare(struct
01603 rsbac_list_lol_reg_item_t
01604 *list,
01605 struct
01606 rsbac_list_lol_item_t
01607 *sublist,
01608 void *subdesc,
01609 struct
01610 rsbac_list_item_t
01611 *new_item_p)
01612 {
01613 struct rsbac_list_item_t *curr;
01614
01615 curr = sublist->curr;
01616 if (!curr)
01617 curr = sublist->head;
01618 if ((list->subcompare(subdesc, &curr[1]) > 0)) {
01619 curr = curr->next;
01620 while (curr && (list->subcompare(subdesc, &curr[1]) > 0)
01621 )
01622 curr = curr->next;
01623 if (curr) {
01624
01625 new_item_p->prev = curr->prev;
01626 new_item_p->next = curr;
01627 curr->prev->next = new_item_p;
01628 curr->prev = new_item_p;
01629 } else {
01630
01631 new_item_p->prev = sublist->tail;
01632 new_item_p->next = NULL;
01633 sublist->tail->next = new_item_p;
01634 sublist->tail = new_item_p;
01635 }
01636 } else {
01637 curr = curr->prev;
01638 while (curr && (list->subcompare(subdesc, &curr[1]) < 0)
01639 )
01640 curr = curr->prev;
01641 if (curr) {
01642
01643 new_item_p->prev = curr;
01644 new_item_p->next = curr->next;
01645 curr->next->prev = new_item_p;
01646 curr->next = new_item_p;
01647 } else {
01648
01649 new_item_p->prev = NULL;
01650 new_item_p->next = sublist->head;
01651 sublist->head->prev = new_item_p;
01652 sublist->head = new_item_p;
01653 }
01654 }
01655 sublist->count++;
01656 sublist->curr = new_item_p;
01657 return new_item_p;
01658 }
01659
01660 static inline struct rsbac_list_item_t *insert_lol_subitem_memcmp(struct
01661 rsbac_list_lol_reg_item_t
01662 *list,
01663 struct
01664 rsbac_list_lol_item_t
01665 *sublist,
01666 void *subdesc,
01667 struct
01668 rsbac_list_item_t
01669 *new_item_p)
01670 {
01671 struct rsbac_list_item_t *curr;
01672
01673 curr = sublist->curr;
01674 if (!curr)
01675 curr = sublist->head;
01676 if (memcmp(subdesc, &curr[1], list->info.subdesc_size) > 0) {
01677 curr = curr->next;
01678 while (curr
01679 && (memcmp(subdesc,
01680 &curr[1], list->info.subdesc_size) > 0)
01681 )
01682 curr = curr->next;
01683 if (curr) {
01684
01685 new_item_p->prev = curr->prev;
01686 new_item_p->next = curr;
01687 curr->prev->next = new_item_p;
01688 curr->prev = new_item_p;
01689 } else {
01690
01691 new_item_p->prev = sublist->tail;
01692 new_item_p->next = NULL;
01693 sublist->tail->next = new_item_p;
01694 sublist->tail = new_item_p;
01695 }
01696 } else {
01697 curr = curr->prev;
01698 while (curr
01699 && (memcmp(subdesc,
01700 &curr[1], list->info.subdesc_size) < 0)
01701 )
01702 curr = curr->prev;
01703 if (curr) {
01704
01705 new_item_p->prev = curr;
01706 new_item_p->next = curr->next;
01707 curr->next->prev = new_item_p;
01708 curr->next = new_item_p;
01709 } else {
01710
01711 new_item_p->prev = NULL;
01712 new_item_p->next = sublist->head;
01713 sublist->head->prev = new_item_p;
01714 sublist->head = new_item_p;
01715 }
01716 }
01717 sublist->count++;
01718 sublist->curr = new_item_p;
01719 return new_item_p;
01720 }
01721
01722 static struct rsbac_list_item_t *add_lol_subitem(struct
01723 rsbac_list_lol_reg_item_t
01724 *list,
01725 struct
01726 rsbac_list_lol_item_t
01727 *sublist,
01728 rsbac_time_t max_age,
01729 void *subdesc,
01730 void *subdata)
01731 {
01732 struct rsbac_list_item_t *new_item_p = NULL;
01733
01734 if (!list || !sublist || !subdesc)
01735 return NULL;
01736 if (list->info.subdata_size && !subdata)
01737 return NULL;
01738
01739 if (!
01740 (new_item_p =
01741 rsbac_kmalloc(sizeof(*new_item_p) + list->info.subdesc_size +
01742 list->info.subdata_size)))
01743 return (NULL);
01744 new_item_p->max_age = max_age;
01745
01746 memcpy(&new_item_p[1], subdesc, list->info.subdesc_size);
01747
01748
01749 if (subdata && list->info.subdata_size)
01750 memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
01751 list->info.subdesc_size, subdata,
01752 list->info.subdata_size);
01753
01754
01755 if (!sublist->head) {
01756 sublist->head = new_item_p;
01757 sublist->tail = new_item_p;
01758 sublist->curr = new_item_p;
01759 sublist->count = 1;
01760 new_item_p->prev = NULL;
01761 new_item_p->next = NULL;
01762 return (new_item_p);
01763 }
01764 if (sublist->count >= list->max_subitems) {
01765 rsbac_kfree(new_item_p);
01766 if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
01767 rsbac_printk(KERN_WARNING "add_lol_subitem(): cannot add subitem to sublist of %s on device %02u:%02u, would be more than %u subitems!\n",
01768 list->name,
01769 RSBAC_MAJOR(list->device),
01770 RSBAC_MINOR(list->device),
01771 list->max_subitems);
01772 return NULL;
01773 }
01774 if (list->subcompare)
01775 return insert_lol_subitem_compare(list, sublist, subdesc,
01776 new_item_p);
01777 else
01778 return insert_lol_subitem_memcmp(list, sublist, subdesc,
01779 new_item_p);
01780 }
01781
01782 static inline struct rsbac_list_lol_item_t *insert_lol_item_compare(struct
01783 rsbac_list_lol_reg_item_t
01784 *list,
01785 void *desc,
01786 struct
01787 rsbac_list_lol_item_t
01788 *new_item_p)
01789 {
01790 struct rsbac_list_lol_item_t *curr;
01791 u_int hash = 0;
01792
01793 if(list->hash_function)
01794 hash = list->hash_function(desc, list->nr_hashes);
01795 curr = list->hashed[hash].curr;
01796 if (!curr)
01797 curr = list->hashed[hash].head;
01798 if ((list->compare(desc, &curr[1]) > 0)) {
01799 curr = curr->next;
01800 while (curr && (list->compare(desc, &curr[1]) > 0)
01801 )
01802 curr = curr->next;
01803 if (curr) {
01804
01805 new_item_p->prev = curr->prev;
01806 new_item_p->next = curr;
01807 curr->prev->next = new_item_p;
01808 curr->prev = new_item_p;
01809 } else {
01810
01811 new_item_p->prev = list->hashed[hash].tail;
01812 new_item_p->next = NULL;
01813 list->hashed[hash].tail->next = new_item_p;
01814 list->hashed[hash].tail = new_item_p;
01815 }
01816 } else {
01817 curr = curr->prev;
01818 while (curr && (list->compare(desc, &curr[1]) < 0)
01819 )
01820 curr = curr->prev;
01821 if (curr) {
01822
01823 new_item_p->prev = curr;
01824 new_item_p->next = curr->next;
01825 curr->next->prev = new_item_p;
01826 curr->next = new_item_p;
01827 } else {
01828
01829 new_item_p->prev = NULL;
01830 new_item_p->next = list->hashed[hash].head;
01831 list->hashed[hash].head->prev = new_item_p;
01832 list->hashed[hash].head = new_item_p;
01833 }
01834 }
01835 list->hashed[hash].count++;
01836 list->hashed[hash].curr = new_item_p;
01837 return new_item_p;
01838 }
01839
01840 static inline struct rsbac_list_lol_item_t *insert_lol_item_memcmp(struct
01841 rsbac_list_lol_reg_item_t
01842 *list,
01843 void *desc,
01844 struct
01845 rsbac_list_lol_item_t
01846 *new_item_p)
01847 {
01848 struct rsbac_list_lol_item_t *curr;
01849 u_int hash = 0;
01850
01851 if(list->hash_function)
01852 hash = list->hash_function(desc, list->nr_hashes);
01853 curr = list->hashed[hash].curr;
01854 if (!curr)
01855 curr = list->hashed[hash].head;
01856 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
01857 curr = curr->next;
01858 while (curr
01859 && (memcmp(desc,
01860 &curr[1], list->info.desc_size) > 0)
01861 )
01862 curr = curr->next;
01863 if (curr) {
01864
01865 new_item_p->prev = curr->prev;
01866 new_item_p->next = curr;
01867 curr->prev->next = new_item_p;
01868 curr->prev = new_item_p;
01869 } else {
01870
01871 new_item_p->prev = list->hashed[hash].tail;
01872 new_item_p->next = NULL;
01873 list->hashed[hash].tail->next = new_item_p;
01874 list->hashed[hash].tail = new_item_p;
01875 }
01876 } else {
01877 curr = curr->prev;
01878 while (curr
01879 && (memcmp(desc,
01880 &curr[1], list->info.desc_size) < 0)
01881 )
01882 curr = curr->prev;
01883 if (curr) {
01884
01885 new_item_p->prev = curr;
01886 new_item_p->next = curr->next;
01887 curr->next->prev = new_item_p;
01888 curr->next = new_item_p;
01889 } else {
01890
01891 new_item_p->prev = NULL;
01892 new_item_p->next = list->hashed[hash].head;
01893 list->hashed[hash].head->prev = new_item_p;
01894 list->hashed[hash].head = new_item_p;
01895 }
01896 }
01897 list->hashed[hash].count++;
01898 list->hashed[hash].curr = new_item_p;
01899 return new_item_p;
01900 }
01901
01902 static struct rsbac_list_lol_item_t *add_lol_item(struct
01903 rsbac_list_lol_reg_item_t
01904 *list,
01905 rsbac_time_t max_age,
01906 void *desc, void *data)
01907 {
01908 struct rsbac_list_lol_item_t *new_item_p = NULL;
01909 u_int hash = 0;
01910
01911 if (!list || !desc)
01912 return NULL;
01913 if (list->info.data_size && !data)
01914 return NULL;
01915
01916 if (!
01917 (new_item_p =
01918 rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size +
01919 list->info.data_size)))
01920 return (NULL);
01921
01922 new_item_p->head = NULL;
01923 new_item_p->tail = NULL;
01924 new_item_p->curr = NULL;
01925 new_item_p->count = 0;
01926 new_item_p->max_age = max_age;
01927
01928 memcpy(&new_item_p[1], desc, list->info.desc_size);
01929
01930
01931 if (data && list->info.data_size)
01932 memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
01933 list->info.desc_size, data, list->info.data_size);
01934
01935 if(list->hash_function)
01936 hash = list->hash_function(desc, list->nr_hashes);
01937 if (!list->hashed[hash].head) {
01938 list->hashed[hash].head = new_item_p;
01939 list->hashed[hash].tail = new_item_p;
01940 list->hashed[hash].curr = new_item_p;
01941 list->hashed[hash].count = 1;
01942 new_item_p->prev = NULL;
01943 new_item_p->next = NULL;
01944 return (new_item_p);
01945 }
01946 if (list->hashed[hash].count >= list->max_items_per_hash) {
01947 rsbac_kfree(new_item_p);
01948 if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
01949 rsbac_printk(KERN_WARNING "add_lol_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
01950 list->name,
01951 hash,
01952 RSBAC_MAJOR(list->device),
01953 RSBAC_MINOR(list->device),
01954 list->max_items_per_hash);
01955 return NULL;
01956 }
01957 if (list->compare)
01958 return insert_lol_item_compare(list, desc, new_item_p);
01959 else
01960 return insert_lol_item_memcmp(list, desc, new_item_p);
01961 }
01962
01963 #ifdef CONFIG_RSBAC_LIST_TRANS
01964 static inline struct rsbac_list_lol_item_t *ta_insert_lol_item_compare(struct
01965 rsbac_list_lol_reg_item_t
01966 *list,
01967 void *desc,
01968 struct
01969 rsbac_list_lol_item_t
01970 *new_item_p)
01971 {
01972 struct rsbac_list_lol_item_t *curr;
01973 u_int hash = 0;
01974
01975 if(list->hash_function)
01976 hash = list->hash_function(desc, list->nr_hashes);
01977 curr = list->hashed[hash].ta_curr;
01978 if (!curr)
01979 curr = list->hashed[hash].ta_head;
01980 if ((list->compare(desc, &curr[1]) > 0)) {
01981 curr = curr->next;
01982 while (curr && (list->compare(desc, &curr[1]) > 0)
01983 )
01984 curr = curr->next;
01985 if (curr) {
01986
01987 new_item_p->prev = curr->prev;
01988 new_item_p->next = curr;
01989 curr->prev->next = new_item_p;
01990 curr->prev = new_item_p;
01991 } else {
01992
01993 new_item_p->prev = list->hashed[hash].ta_tail;
01994 new_item_p->next = NULL;
01995 list->hashed[hash].ta_tail->next = new_item_p;
01996 list->hashed[hash].ta_tail = new_item_p;
01997 }
01998 } else {
01999 curr = curr->prev;
02000 while (curr && (list->compare(desc, &curr[1]) < 0)
02001 )
02002 curr = curr->prev;
02003 if (curr) {
02004
02005 new_item_p->prev = curr;
02006 new_item_p->next = curr->next;
02007 curr->next->prev = new_item_p;
02008 curr->next = new_item_p;
02009 } else {
02010
02011 new_item_p->prev = NULL;
02012 new_item_p->next = list->hashed[hash].ta_head;
02013 list->hashed[hash].ta_head->prev = new_item_p;
02014 list->hashed[hash].ta_head = new_item_p;
02015 }
02016 }
02017 list->hashed[hash].ta_count++;
02018 list->hashed[hash].ta_curr = new_item_p;
02019 return new_item_p;
02020 }
02021
02022 static inline struct rsbac_list_lol_item_t *ta_insert_lol_item_memcmp(struct
02023 rsbac_list_lol_reg_item_t
02024 *list,
02025 void *desc,
02026 struct
02027 rsbac_list_lol_item_t
02028 *new_item_p)
02029 {
02030 struct rsbac_list_lol_item_t *curr;
02031 u_int hash = 0;
02032
02033 if(list->hash_function)
02034 hash = list->hash_function(desc, list->nr_hashes);
02035 curr = list->hashed[hash].ta_curr;
02036 if (!curr)
02037 curr = list->hashed[hash].ta_head;
02038 if (memcmp(desc, &curr[1], list->info.desc_size) > 0) {
02039 curr = curr->next;
02040 while (curr
02041 && (memcmp(desc,
02042 &curr[1], list->info.desc_size) > 0)
02043 )
02044 curr = curr->next;
02045 if (curr) {
02046
02047 new_item_p->prev = curr->prev;
02048 new_item_p->next = curr;
02049 curr->prev->next = new_item_p;
02050 curr->prev = new_item_p;
02051 } else {
02052
02053 new_item_p->prev = list->hashed[hash].ta_tail;
02054 new_item_p->next = NULL;
02055 list->hashed[hash].ta_tail->next = new_item_p;
02056 list->hashed[hash].ta_tail = new_item_p;
02057 }
02058 } else {
02059 curr = curr->prev;
02060 while (curr
02061 && (memcmp(desc,
02062 &curr[1], list->info.desc_size) < 0)
02063 )
02064 curr = curr->prev;
02065 if (curr) {
02066
02067 new_item_p->prev = curr;
02068 new_item_p->next = curr->next;
02069 curr->next->prev = new_item_p;
02070 curr->next = new_item_p;
02071 } else {
02072
02073 new_item_p->prev = NULL;
02074 new_item_p->next = list->hashed[hash].ta_head;
02075 list->hashed[hash].ta_head->prev = new_item_p;
02076 list->hashed[hash].ta_head = new_item_p;
02077 }
02078 }
02079 list->hashed[hash].ta_count++;
02080 list->hashed[hash].ta_curr = new_item_p;
02081 return new_item_p;
02082 }
02083
02084 static struct rsbac_list_lol_item_t *ta_add_lol_item(rsbac_list_ta_number_t
02085 ta_number,
02086 struct
02087 rsbac_list_lol_reg_item_t
02088 *list,
02089 rsbac_time_t max_age,
02090 void *desc,
02091 void *data)
02092 {
02093 struct rsbac_list_lol_item_t *new_item_p = NULL;
02094 u_int hash = 0;
02095
02096 if (!list || !desc)
02097 return NULL;
02098 if (list->info.data_size && !data)
02099 return NULL;
02100 if (!ta_number)
02101 return add_lol_item(list, max_age, desc, data);
02102
02103 if (!
02104 (new_item_p =
02105 rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size +
02106 list->info.data_size)))
02107 return (NULL);
02108
02109 new_item_p->head = NULL;
02110 new_item_p->tail = NULL;
02111 new_item_p->curr = NULL;
02112 new_item_p->count = 0;
02113 new_item_p->max_age = max_age;
02114 new_item_p->prev = NULL;
02115 new_item_p->next = NULL;
02116
02117 memcpy(&new_item_p[1], desc, list->info.desc_size);
02118
02119
02120 if (data && list->info.data_size)
02121 memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) +
02122 list->info.desc_size, data, list->info.data_size);
02123
02124 if(list->hash_function)
02125 hash = list->hash_function(desc, list->nr_hashes);
02126 if (!list->hashed[hash].ta_copied) {
02127 if (ta_lol_copy(ta_number, list, hash)) {
02128 rsbac_kfree(new_item_p);
02129 return NULL;
02130 }
02131 } else {
02132 if (list->hashed[hash].ta_copied != ta_number) {
02133 rsbac_kfree(new_item_p);
02134 return NULL;
02135 }
02136 }
02137
02138 if (!list->hashed[hash].ta_head) {
02139 list->hashed[hash].ta_head = new_item_p;
02140 list->hashed[hash].ta_tail = new_item_p;
02141 list->hashed[hash].ta_curr = new_item_p;
02142 list->hashed[hash].ta_count = 1;
02143 return (new_item_p);
02144 }
02145 if (list->hashed[hash].ta_count >= list->max_items_per_hash) {
02146 rsbac_kfree(new_item_p);
02147 if (!(list->flags & RSBAC_LIST_NO_MAX_WARN))
02148 rsbac_printk(KERN_WARNING "ta_add_lol_item(): cannot add item to list %s, hash %u on device %02u:%02u, would be more than %u items!\n",
02149 list->name,
02150 hash,
02151 RSBAC_MAJOR(list->device),
02152 RSBAC_MINOR(list->device),
02153 list->max_items_per_hash);
02154 return NULL;
02155 }
02156 if (list->compare)
02157 return ta_insert_lol_item_compare(list, desc, new_item_p);
02158 else
02159 return ta_insert_lol_item_memcmp(list, desc, new_item_p);
02160 }
02161 #endif
02162
02163
02164
02165
02166 static inline struct rsbac_list_reg_item_t *create_reg(
02167 struct rsbac_list_info_t *info_p,
02168 u_int flags,
02169 rsbac_list_compare_function_t * compare,
02170 rsbac_list_get_conv_t * get_conv,
02171 void *def_data,
02172 char *name,
02173 kdev_t device,
02174 u_int nr_hashes,
02175 rsbac_list_hash_function_t hash_function,
02176 char * old_name_base)
02177 {
02178 struct rsbac_list_reg_item_t *new_item_p = NULL;
02179 int i;
02180
02181 if (!(new_item_p = rsbac_kmalloc(sizeof(*new_item_p))))
02182 return (NULL);
02183 if (!(new_item_p->hashed = rsbac_kmalloc(nr_hashes*sizeof(struct rsbac_list_hashed_t)))) {
02184 rsbac_kfree(new_item_p);
02185 return (NULL);
02186 }
02187 new_item_p->info = *info_p;
02188 if (!def_data)
02189 flags &= ~RSBAC_LIST_DEF_DATA;
02190 new_item_p->flags = flags;
02191 new_item_p->compare = compare;
02192 new_item_p->get_conv = get_conv;
02193 if (flags & RSBAC_LIST_DEF_DATA) {
02194 new_item_p->def_data = rsbac_kmalloc(info_p->data_size);
02195 if (new_item_p->def_data)
02196 memcpy(new_item_p->def_data, def_data,
02197 info_p->data_size);
02198 else {
02199 rsbac_kfree(new_item_p->hashed);
02200 rsbac_kfree(new_item_p);
02201 return NULL;
02202 }
02203 } else
02204 new_item_p->def_data = NULL;
02205 if (name) {
02206 strncpy(new_item_p->name, name, RSBAC_LIST_MAX_FILENAME);
02207 new_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
02208 } else {
02209 strcpy(new_item_p->name, RSBAC_LIST_NONAME);
02210 }
02211 new_item_p->nr_hashes = nr_hashes;
02212 if (flags & RSBAC_LIST_NO_MAX)
02213 new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS_LIMIT;
02214 else
02215 new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS;
02216 new_item_p->hash_function = hash_function;
02217 if (old_name_base) {
02218 strncpy(new_item_p->old_name_base, old_name_base, RSBAC_LIST_MAX_FILENAME);
02219 new_item_p->old_name_base[RSBAC_LIST_MAX_FILENAME] = 0;
02220 } else {
02221 new_item_p->old_name_base[0] = 0;
02222 }
02223 new_item_p->device = device;
02224 new_item_p->lock = RW_LOCK_UNLOCKED;
02225 for(i=0; i<nr_hashes; i++) {
02226 new_item_p->hashed[i].head = NULL;
02227 new_item_p->hashed[i].tail = NULL;
02228 new_item_p->hashed[i].curr = NULL;
02229 new_item_p->hashed[i].count = 0;
02230 #ifdef CONFIG_RSBAC_LIST_TRANS
02231 new_item_p->hashed[i].ta_copied = 0;
02232 new_item_p->hashed[i].ta_head = NULL;
02233 new_item_p->hashed[i].ta_tail = NULL;
02234 new_item_p->hashed[i].ta_curr = NULL;
02235 new_item_p->hashed[i].ta_count = 0;
02236 #endif
02237 }
02238 new_item_p->dirty = FALSE;
02239 if (flags & RSBAC_LIST_NO_WRITE)
02240 new_item_p->no_write = TRUE;
02241 else
02242 new_item_p->no_write = FALSE;
02243 new_item_p->lastchange.sec = 0;
02244 new_item_p->lastchange.nsec = 0;
02245 new_item_p->self = new_item_p;
02246 return new_item_p;
02247 }
02248
02249
02250 static struct rsbac_list_reg_item_t *add_reg(struct rsbac_list_reg_item_t
02251 *new_item_p)
02252 {
02253 if (!reg_head.head) {
02254 reg_head.head = new_item_p;
02255 reg_head.tail = new_item_p;
02256 reg_head.curr = new_item_p;
02257 reg_head.count = 1;
02258 new_item_p->prev = NULL;
02259 new_item_p->next = NULL;
02260 } else {
02261 new_item_p->prev = reg_head.tail;
02262 new_item_p->next = NULL;
02263 reg_head.tail->next = new_item_p;
02264 reg_head.tail = new_item_p;
02265 reg_head.curr = new_item_p;
02266 reg_head.count++;
02267 }
02268 return (new_item_p);
02269 }
02270
02271
02272 static inline struct rsbac_list_lol_reg_item_t *create_lol_reg(
02273 struct rsbac_list_lol_info_t *info_p,
02274 u_int flags,
02275 rsbac_list_compare_function_t *compare,
02276 rsbac_list_compare_function_t *subcompare,
02277 rsbac_list_get_conv_t *get_conv,
02278 rsbac_list_get_conv_t *get_subconv,
02279 void *def_data,
02280 void *def_subdata,
02281 char *name,
02282 kdev_t device,
02283 u_int nr_hashes,
02284 rsbac_list_hash_function_t hash_function,
02285 char * old_name_base)
02286 {
02287 struct rsbac_list_lol_reg_item_t *new_item_p = NULL;
02288 int i;
02289
02290 if (!(new_item_p = rsbac_kmalloc(sizeof(*new_item_p))))
02291 return (NULL);
02292 if (!(new_item_p->hashed = rsbac_kmalloc(nr_hashes*sizeof(struct rsbac_list_lol_hashed_t)))) {
02293 rsbac_kfree(new_item_p);
02294 return (NULL);
02295 }
02296 new_item_p->info = *info_p;
02297 if (info_p->data_size && !def_data)
02298 flags &= ~RSBAC_LIST_DEF_DATA;
02299 if (!def_subdata)
02300 flags &= ~RSBAC_LIST_DEF_SUBDATA;
02301 new_item_p->flags = flags;
02302 new_item_p->compare = compare;
02303 new_item_p->subcompare = subcompare;
02304 new_item_p->get_conv = get_conv;
02305 new_item_p->get_subconv = get_subconv;
02306 if ((flags & RSBAC_LIST_DEF_DATA)
02307 && (info_p->data_size)
02308 ) {
02309 new_item_p->def_data = rsbac_kmalloc(info_p->data_size);
02310 if (new_item_p->def_data)
02311 memcpy(new_item_p->def_data, def_data,
02312 info_p->data_size);
02313 else {
02314 rsbac_kfree(new_item_p->hashed);
02315 rsbac_kfree(new_item_p);
02316 return NULL;
02317 }
02318 } else
02319 new_item_p->def_data = NULL;
02320 if (flags & RSBAC_LIST_DEF_SUBDATA) {
02321 new_item_p->def_subdata =
02322 rsbac_kmalloc(info_p->subdata_size);
02323 if (new_item_p->def_subdata)
02324 memcpy(new_item_p->def_subdata, def_subdata,
02325 info_p->subdata_size);
02326 else {
02327 if (new_item_p->def_data)
02328 rsbac_kfree(new_item_p->def_data);
02329 rsbac_kfree(new_item_p->hashed);
02330 rsbac_kfree(new_item_p);
02331 return NULL;
02332 }
02333 } else
02334 new_item_p->def_subdata = NULL;
02335 if (name) {
02336 strncpy(new_item_p->name, name, RSBAC_LIST_MAX_FILENAME);
02337 new_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
02338 } else {
02339 strcpy(new_item_p->name, RSBAC_LIST_NONAME);
02340 }
02341 new_item_p->nr_hashes = nr_hashes;
02342 if (flags & RSBAC_LIST_NO_MAX) {
02343 new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS_LIMIT;
02344 new_item_p->max_subitems = RSBAC_LIST_MAX_NR_ITEMS_LIMIT;
02345 } else {
02346 new_item_p->max_items_per_hash = RSBAC_LIST_MAX_NR_ITEMS;
02347 new_item_p->max_subitems = RSBAC_LIST_MAX_NR_SUBITEMS;
02348 }
02349 new_item_p->hash_function = hash_function;
02350 if (old_name_base) {
02351 strncpy(new_item_p->old_name_base, old_name_base, RSBAC_LIST_MAX_FILENAME);
02352 new_item_p->old_name_base[RSBAC_LIST_MAX_FILENAME] = 0;
02353 } else
02354 new_item_p->old_name_base[0] = 0;
02355 new_item_p->device = device;
02356 new_item_p->lock = RW_LOCK_UNLOCKED;
02357 for(i=0; i<nr_hashes; i++) {
02358 new_item_p->hashed[i].head = NULL;
02359 new_item_p->hashed[i].tail = NULL;
02360 new_item_p->hashed[i].curr = NULL;
02361 new_item_p->hashed[i].count = 0;
02362 #ifdef CONFIG_RSBAC_LIST_TRANS
02363 new_item_p->hashed[i].ta_copied = 0;
02364 new_item_p->hashed[i].ta_head = NULL;
02365 new_item_p->hashed[i].ta_tail = NULL;
02366 new_item_p->hashed[i].ta_curr = NULL;
02367 new_item_p->hashed[i].ta_count = 0;
02368 #endif
02369 }
02370 new_item_p->dirty = FALSE;
02371 if (flags & RSBAC_LIST_NO_WRITE)
02372 new_item_p->no_write = TRUE;
02373 else
02374 new_item_p->no_write = FALSE;
02375 new_item_p->lastchange.sec = 0;
02376 new_item_p->lastchange.nsec = 0;
02377 new_item_p->self = new_item_p;
02378 return (new_item_p);
02379 }
02380
02381
02382 static struct rsbac_list_lol_reg_item_t *add_lol_reg(struct
02383 rsbac_list_lol_reg_item_t
02384 *new_item_p)
02385 {
02386 if (!lol_reg_head.head) {
02387 lol_reg_head.head = new_item_p;
02388 lol_reg_head.tail = new_item_p;
02389 lol_reg_head.curr = new_item_p;
02390 lol_reg_head.count = 1;
02391 new_item_p->prev = NULL;
02392 new_item_p->next = NULL;
02393 } else {
02394 new_item_p->prev = lol_reg_head.tail;
02395 new_item_p->next = NULL;
02396 lol_reg_head.tail->next = new_item_p;
02397 lol_reg_head.tail = new_item_p;
02398 lol_reg_head.curr = new_item_p;
02399 lol_reg_head.count++;
02400 };
02401 return (new_item_p);
02402 }
02403
02404
02405
02406 static inline void do_remove_item(struct rsbac_list_reg_item_t *list,
02407 struct rsbac_list_item_t *item_p,
02408 u_int hash)
02409 {
02410 if (!list || !item_p)
02411 return;
02412
02413 if ((list->hashed[hash].head == item_p)) {
02414 if ((list->hashed[hash].tail == item_p)) {
02415 list->hashed[hash].head = NULL;
02416 list->hashed[hash].tail = NULL;
02417 } else {
02418 item_p->next->prev = NULL;
02419 list->hashed[hash].head = item_p->next;
02420 };
02421 } else {
02422 if ((list->hashed[hash].tail == item_p)) {
02423 item_p->prev->next = NULL;
02424 list->hashed[hash].tail = item_p->prev;
02425 } else {
02426 item_p->prev->next = item_p->next;
02427 item_p->next->prev = item_p->prev;
02428 }
02429 }
02430
02431 list->hashed[hash].curr = NULL;
02432
02433 list->hashed[hash].count--;
02434
02435 rsbac_kfree(item_p);
02436 }
02437
02438 static void remove_item(struct rsbac_list_reg_item_t *list, void *desc)
02439 {
02440 struct rsbac_list_item_t *item_p;
02441 u_int hash = 0;
02442
02443 if (!list || !desc)
02444 return;
02445 if(list->hash_function)
02446 hash = list->hash_function(desc, list->nr_hashes);
02447
02448 if ((item_p = lookup_item(list, desc))) {
02449 do_remove_item(list, item_p, hash);
02450 }
02451 }
02452
02453 static void remove_all_items(struct rsbac_list_reg_item_t *list, u_int hash)
02454 {
02455 struct rsbac_list_item_t *item_p;
02456 struct rsbac_list_item_t *next_item_p;
02457
02458
02459 item_p = list->hashed[hash].head;
02460 while (item_p) {
02461 next_item_p = item_p->next;
02462 rsbac_kfree(item_p);
02463 item_p = next_item_p;
02464 }
02465 list->hashed[hash].head = NULL;
02466 list->hashed[hash].tail = NULL;
02467 list->hashed[hash].curr = NULL;
02468 list->hashed[hash].count = 0;
02469 }
02470
02471 #ifdef CONFIG_RSBAC_LIST_TRANS
02472 static void ta_do_remove_item(struct rsbac_list_reg_item_t *list,
02473 struct rsbac_list_item_t *item_p,
02474 u_int hash)
02475 {
02476 if (!list || !item_p)
02477 return;
02478
02479 if ((list->hashed[hash].ta_head == item_p)) {
02480 if ((list->hashed[hash].ta_tail == item_p)) {
02481 list->hashed[hash].ta_head = NULL;
02482 list->hashed[hash].ta_tail = NULL;
02483 } else {
02484 item_p->next->prev = NULL;
02485 list->hashed[hash].ta_head = item_p->next;
02486 }
02487 } else {
02488 if ((list->hashed[hash].ta_tail == item_p)) {
02489 item_p->prev->next = NULL;
02490 list->hashed[hash].ta_tail = item_p->prev;
02491 } else {
02492 item_p->prev->next = item_p->next;
02493 item_p->next->prev = item_p->prev;
02494 }
02495 }
02496
02497 list->hashed[hash].ta_curr = NULL;
02498
02499 list->hashed[hash].ta_count--;
02500
02501 rsbac_kfree(item_p);
02502 }
02503
02504 static void ta_remove_item(rsbac_list_ta_number_t ta_number,
02505 struct rsbac_list_reg_item_t *list, void *desc)
02506 {
02507 struct rsbac_list_item_t *item_p;
02508 u_int hash = 0;
02509
02510 if (!list || !desc)
02511 return;
02512 if (!ta_number)
02513 return remove_item(list, desc);
02514 if(list->hash_function)
02515 hash = list->hash_function(desc, list->nr_hashes);
02516
02517 if ((item_p = ta_lookup_item(ta_number, list, desc))) {
02518 ta_do_remove_item(list, item_p, hash);
02519 }
02520 }
02521
02522 static void ta_remove_all_items(struct rsbac_list_reg_item_t *list, u_int hash)
02523 {
02524 struct rsbac_list_item_t *item_p;
02525 struct rsbac_list_item_t *next_item_p;
02526
02527
02528 item_p = list->hashed[hash].ta_head;
02529 while (item_p) {
02530 next_item_p = item_p->next;
02531 rsbac_kfree(item_p);
02532 item_p = next_item_p;
02533 }
02534 list->hashed[hash].ta_head = NULL;
02535 list->hashed[hash].ta_tail = NULL;
02536 list->hashed[hash].ta_curr = NULL;
02537 list->hashed[hash].ta_count = 0;
02538 }
02539 #endif
02540
02541 static void do_remove_lol_subitem(struct rsbac_list_lol_item_t *sublist,
02542 struct rsbac_list_item_t *item_p)
02543 {
02544 if (!sublist || !item_p)
02545 return;
02546
02547 if ((sublist->head == item_p)) {
02548 if ((sublist->tail == item_p)) {
02549 sublist->head = NULL;
02550 sublist->tail = NULL;
02551 } else {
02552 item_p->next->prev = NULL;
02553 sublist->head = item_p->next;
02554 }
02555 } else {
02556 if ((sublist->tail == item_p)) {
02557 item_p->prev->next = NULL;
02558 sublist->tail = item_p->prev;
02559 } else {
02560 item_p->prev->next = item_p->next;
02561 item_p->next->prev = item_p->prev;
02562 }
02563 }
02564
02565 sublist->curr = NULL;
02566
02567 sublist->count--;
02568
02569 rsbac_kfree(item_p);
02570 }
02571
02572 static void remove_lol_subitem(struct rsbac_list_lol_reg_item_t *list,
02573 struct rsbac_list_lol_item_t *sublist,
02574 void *subdesc)
02575 {
02576 struct rsbac_list_item_t *item_p;
02577
02578 if (!list || !sublist || !subdesc)
02579 return;
02580
02581
02582 if ((item_p = lookup_lol_subitem(list, sublist, subdesc))) {
02583 do_remove_lol_subitem(sublist, item_p);
02584 }
02585 }
02586
02587
02588 static void do_remove_lol_item(struct rsbac_list_lol_reg_item_t *list,
02589 struct rsbac_list_lol_item_t *item_p,
02590 u_int hash)
02591 {
02592 struct rsbac_list_item_t *subitem_p;
02593 struct rsbac_list_item_t *next_subitem_p;
02594
02595 if (!list || !item_p)
02596 return;
02597
02598 if ((list->hashed[hash].head == item_p)) {
02599 if ((list->hashed[hash].tail == item_p)) {
02600 list->hashed[hash].head = NULL;
02601 list->hashed[hash].tail = NULL;
02602 } else {
02603 #ifdef CONFIG_RSBAC_DEBUG
02604 if (!item_p->next) {
02605 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02606 list->name);
02607 } else
02608 #endif
02609 {
02610 item_p->next->prev = NULL;
02611 list->hashed[hash].head = item_p->next;
02612 }
02613 }
02614 } else {
02615 if ((list->hashed[hash].tail == item_p)) {
02616 #ifdef CONFIG_RSBAC_DEBUG
02617 if (!item_p->prev) {
02618 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02619 list->name);
02620 } else
02621 #endif
02622 {
02623 item_p->prev->next = NULL;
02624 list->hashed[hash].tail = item_p->prev;
02625 }
02626 } else {
02627 #ifdef CONFIG_RSBAC_DEBUG
02628 if (!item_p->prev) {
02629 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02630 list->name);
02631 } else if (!item_p->next) {
02632 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02633 list->name);
02634 } else
02635 #endif
02636 {
02637 item_p->prev->next = item_p->next;
02638 item_p->next->prev = item_p->prev;
02639 }
02640 }
02641 }
02642
02643 list->hashed[hash].curr = NULL;
02644
02645 list->hashed[hash].count--;
02646
02647 subitem_p = item_p->head;
02648 while (subitem_p) {
02649 next_subitem_p = subitem_p->next;
02650 rsbac_kfree(subitem_p);
02651 subitem_p = next_subitem_p;
02652 }
02653
02654 rsbac_kfree(item_p);
02655 }
02656
02657 static void remove_lol_item(struct rsbac_list_lol_reg_item_t *list,
02658 void *desc)
02659 {
02660 struct rsbac_list_lol_item_t *item_p;
02661 u_int hash = 0;
02662
02663 if (!list || !desc)
02664 return;
02665
02666 if(list->hash_function)
02667 hash = list->hash_function(desc, list->nr_hashes);
02668
02669 if ((item_p = lookup_lol_item(list, desc))) {
02670 do_remove_lol_item(list, item_p, hash);
02671 }
02672 }
02673
02674 #ifdef CONFIG_RSBAC_LIST_TRANS
02675 static void ta_do_remove_lol_item(struct rsbac_list_lol_reg_item_t *list,
02676 struct rsbac_list_lol_item_t *item_p,
02677 u_int hash)
02678 {
02679 struct rsbac_list_item_t *subitem_p;
02680 struct rsbac_list_item_t *next_subitem_p;
02681
02682 if (!list || !item_p)
02683 return;
02684
02685 if ((list->hashed[hash].ta_head == item_p)) {
02686 if ((list->hashed[hash].ta_tail == item_p)) {
02687 list->hashed[hash].ta_head = NULL;
02688 list->hashed[hash].ta_tail = NULL;
02689 } else {
02690 #ifdef CONFIG_RSBAC_DEBUG
02691 if (!item_p->next) {
02692 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02693 list->name);
02694 } else
02695 #endif
02696 {
02697 item_p->next->prev = NULL;
02698 list->hashed[hash].ta_head = item_p->next;
02699 }
02700 }
02701 } else {
02702 if ((list->hashed[hash].ta_tail == item_p)) {
02703 #ifdef CONFIG_RSBAC_DEBUG
02704 if (!item_p->prev) {
02705 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02706 list->name);
02707 } else
02708 #endif
02709 {
02710 item_p->prev->next = NULL;
02711 list->hashed[hash].ta_tail = item_p->prev;
02712 }
02713 } else {
02714 #ifdef CONFIG_RSBAC_DEBUG
02715 if (!item_p->prev) {
02716 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02717 list->name);
02718 } else if (!item_p->next) {
02719 rsbac_printk(KERN_WARNING "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02720 list->name);
02721 } else
02722 #endif
02723 {
02724 item_p->prev->next = item_p->next;
02725 item_p->next->prev = item_p->prev;
02726 }
02727 }
02728 }
02729
02730 list->hashed[hash].ta_curr = NULL;
02731
02732 list->hashed[hash].ta_count--;
02733
02734
02735 subitem_p = item_p->head;
02736 while (subitem_p) {
02737 next_subitem_p = subitem_p->next;
02738 rsbac_kfree(subitem_p);
02739 subitem_p = next_subitem_p;
02740 }
02741
02742 rsbac_kfree(item_p);
02743 }
02744
02745 static void ta_remove_lol_item(rsbac_list_ta_number_t ta_number,
02746 struct rsbac_list_lol_reg_item_t *list,
02747 void *desc)
02748 {
02749 struct rsbac_list_lol_item_t *item_p;
02750 u_int hash = 0;
02751
02752 if (!list || !desc)
02753 return;
02754
02755 if(list->hash_function)
02756 hash = list->hash_function(desc, list->nr_hashes);
02757
02758 if ((item_p = ta_lookup_lol_item(ta_number, list, desc))) {
02759 ta_do_remove_lol_item(list, item_p, hash);
02760 }
02761 }
02762 #endif
02763
02764 static void remove_all_lol_subitems(struct rsbac_list_lol_item_t *sublist)
02765 {
02766 struct rsbac_list_item_t *subitem_p;
02767 struct rsbac_list_item_t *next_subitem_p;
02768
02769
02770 subitem_p = sublist->head;
02771 while (subitem_p) {
02772 next_subitem_p = subitem_p->next;
02773 rsbac_kfree(subitem_p);
02774 subitem_p = next_subitem_p;
02775 }
02776 sublist->head = NULL;
02777 sublist->tail = NULL;
02778 sublist->curr = NULL;
02779 sublist->count = 0;
02780 }
02781
02782 static void remove_all_lol_items(struct rsbac_list_lol_reg_item_t *list, u_int hash)
02783 {
02784 struct rsbac_list_lol_item_t *item_p;
02785 struct rsbac_list_lol_item_t *next_item_p;
02786 struct rsbac_list_item_t *subitem_p;
02787 struct rsbac_list_item_t *next_subitem_p;
02788
02789
02790 item_p = list->hashed[hash].head;
02791 while (item_p) {
02792
02793 subitem_p = item_p->head;
02794 while (subitem_p) {
02795 next_subitem_p = subitem_p->next;
02796 rsbac_kfree(subitem_p);
02797 subitem_p = next_subitem_p;
02798 }
02799 next_item_p = item_p->next;
02800 rsbac_kfree(item_p);
02801 item_p = next_item_p;
02802 }
02803 list->hashed[hash].head = NULL;
02804 list->hashed[hash].tail = NULL;
02805 list->hashed[hash].curr = NULL;
02806 list->hashed[hash].count = 0;
02807 }
02808
02809 #ifdef CONFIG_RSBAC_LIST_TRANS
02810 static void ta_remove_all_lol_items(struct rsbac_list_lol_reg_item_t *list,
02811 u_int hash)
02812 {
02813 struct rsbac_list_lol_item_t *item_p;
02814 struct rsbac_list_lol_item_t *next_item_p;
02815 struct rsbac_list_item_t *subitem_p;
02816 struct rsbac_list_item_t *next_subitem_p;
02817
02818
02819 item_p = list->hashed[hash].ta_head;
02820 while (item_p) {
02821
02822 subitem_p = item_p->head;
02823 while (subitem_p) {
02824 next_subitem_p = subitem_p->next;
02825 rsbac_kfree(subitem_p);
02826 subitem_p = next_subitem_p;
02827 }
02828 next_item_p = item_p->next;
02829 rsbac_kfree(item_p);
02830 item_p = next_item_p;
02831 }
02832 list->hashed[hash].ta_head = NULL;
02833 list->hashed[hash].ta_tail = NULL;
02834 list->hashed[hash].ta_curr = NULL;
02835 list->hashed[hash].ta_count = 0;
02836 }
02837 #endif
02838
02839
02840
02841
02842 static void clear_reg(struct rsbac_list_reg_item_t *item_p)
02843 {
02844 int i;
02845
02846 if (item_p) {
02847
02848 for (i=0; i<item_p->nr_hashes; i++) {
02849 remove_all_items(item_p, i);
02850 #ifdef CONFIG_RSBAC_LIST_TRANS
02851 if(item_p->hashed[i].ta_copied)
02852 ta_remove_all_items(item_p, i);
02853 #endif
02854 }
02855 if (item_p->def_data)
02856 rsbac_kfree(item_p->def_data);
02857 rsbac_kfree(item_p->hashed);
02858 rsbac_kfree(item_p);
02859 }
02860 }
02861
02862
02863 static void remove_reg(struct rsbac_list_reg_item_t *handle)
02864 {
02865 struct rsbac_list_reg_item_t *item_p;
02866
02867
02868 if ((item_p = lookup_reg(handle))) {
02869
02870 item_p->self = NULL;
02871 if ((reg_head.head == item_p)) {
02872 if ((reg_head.tail == item_p)) {
02873 reg_head.head = NULL;
02874 reg_head.tail = NULL;
02875 } else {
02876 item_p->next->prev = NULL;
02877 reg_head.head = item_p->next;
02878 }
02879 } else {
02880 if ((reg_head.tail == item_p)) {
02881 item_p->prev->next = NULL;
02882 reg_head.tail = item_p->prev;
02883 } else {
02884 item_p->prev->next = item_p->next;
02885 item_p->next->prev = item_p->prev;
02886 }
02887 }
02888
02889
02890 reg_head.curr = NULL;
02891
02892 reg_head.count--;
02893
02894 clear_reg(item_p);
02895 }
02896 }
02897
02898
02899 static void clear_lol_reg(struct rsbac_list_lol_reg_item_t *item_p)
02900 {
02901 int i;
02902
02903 if (item_p) {
02904
02905 for (i=0; i<item_p->nr_hashes; i++) {
02906 remove_all_lol_items(item_p, i);
02907 #ifdef CONFIG_RSBAC_LIST_TRANS
02908 if(item_p->hashed[i].ta_copied)
02909 ta_remove_all_lol_items(item_p, i);
02910 #endif
02911 }
02912 if (item_p->def_data)
02913 rsbac_kfree(item_p->def_data);
02914 if (item_p->def_subdata)
02915 rsbac_kfree(item_p->def_subdata);
02916 rsbac_kfree(item_p->hashed);
02917 rsbac_kfree(item_p);
02918 }
02919 }
02920
02921
02922 static void remove_lol_reg(struct rsbac_list_lol_reg_item_t *handle)
02923 {
02924 struct rsbac_list_lol_reg_item_t *item_p;
02925
02926
02927 if ((item_p = lookup_lol_reg(handle))) {
02928
02929 item_p->self = NULL;
02930 if ((lol_reg_head.head == item_p)) {
02931 if ((lol_reg_head.tail == item_p)) {
02932 lol_reg_head.head = NULL;
02933 lol_reg_head.tail = NULL;
02934 } else {
02935 item_p->next->prev = NULL;
02936 lol_reg_head.head = item_p->next;
02937 };
02938 } else {
02939 if ((lol_reg_head.tail == item_p)) {
02940 item_p->prev->next = NULL;
02941 lol_reg_head.tail = item_p->prev;
02942 } else {
02943 item_p->prev->next = item_p->next;
02944 item_p->next->prev = item_p->prev;
02945 }
02946 }
02947
02948
02949 lol_reg_head.curr = NULL;
02950
02951 lol_reg_head.count--;
02952
02953 clear_lol_reg(item_p);
02954 }
02955 }
02956
02957 #define touch(x)
02958
02959 #define lol_touch(x)
02960
02961
02962
02963
02964
02965 static int do_read_list(struct rsbac_list_reg_item_t *list, char * name)
02966 {
02967 struct file *file_p;
02968 int err = 0;
02969 int tmperr;
02970 int converr;
02971 rsbac_version_t list_version;
02972 u_long read_count = 0;
02973 u_long flags;
02974 char *old_buf;
02975 char *new_buf;
02976 char *old_data;
02977 char *new_data;
02978 struct rsbac_list_info_t *list_info_p;
02979 rsbac_list_count_t list_count;
02980 rsbac_time_t timestamp;
02981 struct rsbac_nanotime_t lastchange;
02982 rsbac_time_t max_age = 0;
02983 rsbac_list_conv_function_t *conv = NULL;
02984 rsbac_boolean_t timeout = FALSE;
02985 mm_segment_t oldfs;
02986
02987 list_info_p = rsbac_kmalloc(sizeof(*list_info_p));
02988 if (!list_info_p)
02989 return -RSBAC_ENOMEM;
02990 file_p = rsbac_kmalloc(sizeof(*file_p));
02991 if (!file_p) {
02992 rsbac_kfree(list_info_p);
02993 return -RSBAC_ENOMEM;
02994 }
02995
02996 if ((err = rsbac_read_open(name, file_p, list->device))) {
02997 rsbac_kfree(list_info_p);
02998 rsbac_kfree(file_p);
02999 return (err);
03000 }
03001
03002
03003
03004
03005
03006
03007
03008
03009 oldfs = get_fs();
03010 set_fs(KERNEL_DS);
03011
03012
03013 tmperr = file_p->f_op->read(file_p,
03014 (__u8 *) & list_version,
03015 sizeof(list_version), &file_p->f_pos);
03016 set_fs(oldfs);
03017
03018 if (tmperr < sizeof(list_version)) {
03019 rsbac_printk(KERN_WARNING "do_read_list(): read error from file!\n");
03020 err = -RSBAC_EREADFAILED;
03021 goto end_read;
03022 }
03023
03024 switch (list_version) {
03025 case RSBAC_LIST_DISK_VERSION:
03026 case RSBAC_LIST_DISK_OLD_VERSION:
03027 break;
03028 default:
03029 rsbac_printk(KERN_WARNING "do_read_list(): wrong on-disk list version %u in file %s, expected %u - error!\n",
03030 list_version,
03031 name, RSBAC_LIST_DISK_VERSION);
03032 err = -RSBAC_EREADFAILED;
03033 goto end_read;
03034 }
03035
03036
03037 set_fs(KERNEL_DS);
03038 tmperr = file_p->f_op->read(file_p,
03039 (__u8 *) & timestamp,
03040 sizeof(timestamp), &file_p->f_pos);
03041 set_fs(oldfs);
03042
03043 if (tmperr < sizeof(timestamp)) {
03044 rsbac_printk(KERN_WARNING "do_read_list(): timestamp read error from file %s!\n",
03045 name);
03046 err = -RSBAC_EREADFAILED;
03047 goto end_read;
03048 }
03049
03050
03051 set_fs(KERNEL_DS);
03052 tmperr = file_p->f_op->read(file_p,
03053 (__u8 *) list_info_p,
03054 sizeof(*list_info_p), &file_p->f_pos);
03055 set_fs(oldfs);
03056
03057 if (tmperr < sizeof(*list_info_p)) {
03058 rsbac_printk(KERN_WARNING "do_read_list(): list info read error from file %s!\n",
03059 name);
03060 err = -RSBAC_EREADFAILED;
03061 goto end_read;
03062 }
03063
03064
03065 if (list_info_p->max_age
03066 && (timestamp + list_info_p->max_age) <= RSBAC_CURRENT_TIME)
03067 timeout = TRUE;
03068
03069
03070 if (list_info_p->key != list->info.key) {
03071 if (timeout) {
03072 rsbac_printk(KERN_WARNING "do_read_list(): accessing timed out list %s with wrong key, ignoring old contents!\n",
03073 name);
03074 goto end_read;
03075 } else {
03076 rsbac_printk(KERN_WARNING "do_read_list(): try to access list %s with wrong key!\n",
03077 name);
03078 err = -EPERM;
03079 goto end_read;
03080 }
03081 }
03082
03083
03084 if (list->flags & RSBAC_LIST_IGNORE_OLD)
03085 goto end_read;
03086
03087 switch (list_version) {
03088 case RSBAC_LIST_DISK_VERSION:
03089 set_fs(KERNEL_DS);
03090 tmperr = file_p->f_op->read(file_p,
03091 (char *) &lastchange,
03092 sizeof(lastchange),
03093 &file_p->f_pos);
03094 set_fs(oldfs);
03095
03096 if (tmperr < sizeof(lastchange)) {
03097 rsbac_printk(KERN_WARNING "do_read_list(): lastchange read error from file %s!\n",
03098 name);
03099 err = -RSBAC_EREADFAILED;
03100 goto end_read;
03101 }
03102 break;
03103 case RSBAC_LIST_DISK_OLD_VERSION:
03104 break;
03105 default:
03106 break;
03107 }
03108
03109 if (list_info_p->version != list->info.version) {
03110 if (list->get_conv)
03111 conv = list->get_conv(list_info_p->version);
03112 if (!conv) {
03113 if (timeout) {
03114 rsbac_printk(KERN_WARNING "do_read_list(): accessing timed out list %s without conversion function, ignoring old contents!\n",
03115 name);
03116 goto end_read;
03117 } else {
03118
03119 if (!
03120 (list->
03121 flags &
03122 RSBAC_LIST_IGNORE_UNSUPP_VERSION)) {
03123 rsbac_printk(KERN_WARNING "do_read_list(): cannot convert list version %u of file %s to version %u!\n",
03124 list_info_p->version,
03125 name,
03126 list->info.version);
03127 err = -RSBAC_EINVALIDVERSION;
03128 }
03129 goto end_read;
03130 }
03131 } else {
03132 rsbac_printk(KERN_WARNING "do_read_list(): converting list version %u of file %s on device %02u:%02u to version %u!\n",
03133 list_info_p->version,
03134 name,
03135 RSBAC_MAJOR(list->device),
03136 RSBAC_MINOR(list->device),
03137 list->info.version);
03138 }
03139 } else {
03140
03141 if ((list_info_p->desc_size != list->info.desc_size)
03142 || (list_info_p->data_size != list->info.data_size)
03143 ) {
03144 if (timeout) {
03145 rsbac_printk(KERN_WARNING "do_read_list(): accessing timed out list %s with wrong desc or data size, ignoring old contents!\n",
03146 name);
03147 goto end_read;
03148 } else {
03149 rsbac_printk(KERN_WARNING "do_read_list(): desc or data size mismatch on list %s!\n",
03150 name);
03151 err = -RSBAC_EINVALIDLIST;
03152 goto end_read;
03153 }
03154 }
03155 }
03156
03157
03158 set_fs(KERNEL_DS);
03159 tmperr = file_p->f_op->read(file_p,
03160 (__u8 *) & list_count,
03161 sizeof(list_count), &file_p->f_pos);
03162 set_fs(oldfs);
03163
03164 if (tmperr < sizeof(list_count)) {
03165 rsbac_printk(KERN_WARNING "do_read_list(): list count read error from file %s!\n",
03166 name);
03167 err = -RSBAC_EREADFAILED;
03168 goto end_read;
03169 }
03170
03171
03172 old_buf =
03173 rsbac_kmalloc(list_info_p->desc_size + list_info_p->data_size);
03174 if (!old_buf) {
03175 rsbac_printk(KERN_WARNING "do_read_list(): cannot allocate memory!\n");
03176 err = -RSBAC_ENOMEM;
03177 goto end_read;
03178 }
03179 new_buf =
03180 rsbac_kmalloc(list->info.desc_size + list->info.data_size);
03181 if (!new_buf) {
03182 rsbac_printk(KERN_WARNING "do_read_list(): cannot allocate memory!\n");
03183 rsbac_kfree(old_buf);
03184 err = -RSBAC_ENOMEM;
03185 goto end_read;
03186 }
03187
03188 if (list_info_p->data_size)
03189 old_data = old_buf + list_info_p->desc_size;
03190 else
03191 old_data = NULL;
03192 if (list->info.data_size)
03193 new_data = new_buf + list->info.desc_size;
03194 else
03195 new_data = NULL;
03196
03197
03198 do {
03199 set_fs(KERNEL_DS);
03200 tmperr = file_p->f_op->read(file_p,
03201 (char *) &max_age,
03202 sizeof(max_age),
03203 &file_p->f_pos);
03204 set_fs(oldfs);
03205 if (conv) {
03206 set_fs(KERNEL_DS);
03207 tmperr = file_p->f_op->read(file_p,
03208 old_buf,
03209 list_info_p->
03210 desc_size +
03211 list_info_p->data_size,
03212 &file_p->f_pos);
03213 set_fs(oldfs);
03214 if (tmperr > 0) {
03215 converr = conv(old_buf, old_data,
03216 new_buf, new_data);
03217 if (converr)
03218 tmperr = converr;
03219 }
03220 } else {
03221 set_fs(KERNEL_DS);
03222 tmperr = file_p->f_op->read(file_p,
03223 new_buf,
03224 list->info.desc_size +
03225 list->info.data_size,
03226 &file_p->f_pos);
03227 set_fs(oldfs);
03228 }
03229
03230 if (tmperr > 0) {
03231
03232 rsbac_write_lock(&list->lock, &flags);
03233 add_item(list, max_age, new_buf, new_data);
03234
03235 rsbac_write_unlock(&list->lock, &flags);
03236 read_count++;
03237
03238
03239
03240 }
03241 }
03242 while (tmperr > 0);
03243
03244 if (tmperr < 0) {
03245 rsbac_printk(KERN_WARNING "do_read_list(): read error from file %s!\n",
03246 name);
03247 err = -RSBAC_EREADFAILED;
03248 }
03249 rsbac_kfree(old_buf);
03250 rsbac_kfree(new_buf);
03251
03252 if (read_count != list_count) {
03253 rsbac_printk(KERN_WARNING "do_read_list(): read %lu, expected %u items from file %s!\n",
03254 read_count, list_count, name);
03255 err = -RSBAC_EREADFAILED;
03256 }
03257
03258 end_read:
03259
03260 rsbac_pr_debug(lists, "%lu entries read.\n", read_count);
03261
03262 rsbac_read_close(file_p);
03263 rsbac_kfree(list_info_p);
03264 rsbac_kfree(file_p);
03265 return (err);
03266 }
03267
03268 static int read_list(struct rsbac_list_reg_item_t *list)
03269 {
03270 int res;
03271 u_int flags;
03272
03273 flags = list->flags;
03274 list->flags |= RSBAC_LIST_NO_MAX;
03275 res = do_read_list(list, list->name);
03276 if((res == -RSBAC_ENOTFOUND) && list->old_name_base[0]) {
03277 char name[RSBAC_MAXNAMELEN];
03278 int i;
03279
03280 rsbac_printk(KERN_INFO "read_list(): list %s on device %02u:%02u not found, trying numbered lists 0 to %u with old name base '%s'\n",
03281 list->name, MAJOR(list->device), MINOR(list->device), RSBAC_LIST_MAX_OLD_HASH-1, list->old_name_base);
03282 for (i=0; i<RSBAC_LIST_MAX_OLD_HASH; i++) {
03283 sprintf(name, "%s%u", list->old_name_base, i);
03284 res = do_read_list(list, name);
03285 if(res && (res != -RSBAC_ENOTFOUND))
03286 return res;
03287 }
03288 list->dirty = TRUE;
03289 }
03290 list->flags = flags;
03291 return res;
03292 }
03293
03294 static int do_read_lol_list(struct rsbac_list_lol_reg_item_t *list, char * name)
03295 {
03296 struct file *file_p;
03297 int err = 0;
03298 int tmperr;
03299 int converr;
03300 rsbac_version_t list_version;
03301 u_long read_count = 0;
03302 u_long flags;
03303 u_long sublen;
03304 u_long i;
03305 char *old_buf;
03306 char *new_buf;
03307 char *old_data;
03308 char *new_data;
03309 char *old_subbuf;
03310 char *new_subbuf;
03311 char *old_subdata;
03312 char *new_subdata;
03313 struct rsbac_list_lol_info_t *list_info_p;
03314 rsbac_list_count_t list_count;
03315 rsbac_time_t timestamp;
03316 struct rsbac_nanotime_t lastchange;
03317 rsbac_time_t max_age = 0;
03318 rsbac_list_conv_function_t *conv = NULL;
03319 rsbac_list_conv_function_t *subconv = NULL;
03320 rsbac_boolean_t timeout = FALSE;
03321 struct rsbac_list_lol_item_t *item_p;
03322 mm_segment_t oldfs;
03323
03324 list_info_p = rsbac_kmalloc(sizeof(*list_info_p));
03325 if (!list_info_p)
03326 return -RSBAC_ENOMEM;
03327 file_p = rsbac_kmalloc(sizeof(*file_p));
03328 if (!file_p) {
03329 rsbac_kfree(list_info_p);
03330 return -RSBAC_ENOMEM;
03331 }
03332
03333 if ((err = rsbac_read_open(name, file_p, list->device))) {
03334 rsbac_kfree(list_info_p);
03335 rsbac_kfree(file_p);
03336 return (err);
03337 }
03338
03339
03340
03341
03342
03343
03344
03345
03346 oldfs = get_fs();
03347 set_fs(KERNEL_DS);
03348
03349
03350 tmperr = file_p->f_op->read(file_p,
03351 (__u8 *) & list_version,
03352 sizeof(list_version), &file_p->f_pos);
03353 set_fs(oldfs);
03354
03355 if (tmperr < sizeof(list_version)) {
03356 printk(KERN_WARNING
03357 "do_read_lol_list(): read error from file!\n");
03358 err = -RSBAC_EREADFAILED;
03359 goto end_read;
03360 }
03361
03362 switch (list_version) {
03363 case RSBAC_LIST_DISK_VERSION:
03364 case RSBAC_LIST_DISK_OLD_VERSION:
03365 break;
03366 default:
03367 rsbac_printk(KERN_WARNING "do_read_lol_list(): wrong on-disk list version %u in file %s, expected %u - error!\n",
03368 list_version,
03369 name, RSBAC_LIST_DISK_VERSION);
03370 err = -RSBAC_EREADFAILED;
03371 goto end_read;
03372 }
03373
03374
03375 set_fs(KERNEL_DS);
03376 tmperr = file_p->f_op->read(file_p,
03377 (__u8 *) & timestamp,
03378 sizeof(timestamp), &file_p->f_pos);
03379 set_fs(oldfs);
03380
03381 if (tmperr < sizeof(timestamp)) {
03382 rsbac_printk(KERN_WARNING "do_read_lol_list(): timestamp read error from file %s!\n",
03383 name);
03384 err = -RSBAC_EREADFAILED;
03385 goto end_read;
03386 }
03387
03388
03389 set_fs(KERNEL_DS);
03390 tmperr = file_p->f_op->read(file_p,
03391 (__u8 *) list_info_p,
03392 sizeof(*list_info_p), &file_p->f_pos);
03393 set_fs(oldfs);
03394
03395 if (tmperr < sizeof(*list_info_p)) {
03396 rsbac_printk(KERN_WARNING "do_read_lol_list(): list info read error from file %s!\n",
03397 name);
03398 err = -RSBAC_EREADFAILED;
03399 goto end_read;
03400 }
03401
03402
03403 if (list_info_p->max_age
03404 && (timestamp + list_info_p->max_age) <= RSBAC_CURRENT_TIME)
03405 timeout = TRUE;
03406
03407
03408 if (list_info_p->key != list->info.key) {
03409 if (timeout) {
03410 rsbac_printk(KERN_WARNING "do_read_lol_list(): accessing timed out list %s with wrong key, ignoring old contents!\n",
03411 name);
03412 goto end_read;
03413 } else {
03414 rsbac_printk(KERN_WARNING "do_read_lol_list(): try to access list %s with wrong key!\n",
03415 name);
03416 err = -EPERM;
03417 goto end_read;
03418 }
03419 }
03420
03421
03422 if (list->flags & RSBAC_LIST_IGNORE_OLD)
03423 goto end_read;
03424
03425 switch (list_version) {
03426 case RSBAC_LIST_DISK_VERSION:
03427 set_fs(KERNEL_DS);
03428 tmperr = file_p->f_op->read(file_p,
03429 (char *) &lastchange,
03430 sizeof(lastchange),
03431 &file_p->f_pos);
03432 set_fs(oldfs);
03433
03434 if (tmperr < sizeof(lastchange)) {
03435 rsbac_printk(KERN_WARNING "read_list(): lastchange read error from file %s!\n",
03436 name);
03437 err = -RSBAC_EREADFAILED;
03438 goto end_read;
03439 }
03440 break;
03441 case RSBAC_LIST_DISK_OLD_VERSION:
03442 break;
03443 default:
03444 break;
03445 }
03446
03447 if (list_info_p->version != list->info.version) {
03448 if (list->get_conv)
03449 conv = list->get_conv(list_info_p->version);
03450 if (list->get_subconv)
03451 subconv = list->get_subconv(list_info_p->version);
03452 if (!conv || !subconv) {
03453 if (timeout) {
03454 rsbac_printk(KERN_WARNING "do_read_lol_list(): accessing timed out list %s without both conversion functions, ignoring old contents!\n",
03455 name);
03456 goto end_read;
03457 } else {
03458
03459 if (!
03460 (list->
03461 flags &
03462 RSBAC_LIST_IGNORE_UNSUPP_VERSION)) {
03463 rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot convert list version %u of file %s to version %u!\n",
03464 list_info_p->version,
03465 name,
03466 list->info.version);
03467 err = -RSBAC_EINVALIDVERSION;
03468 }
03469 goto end_read;
03470 }
03471 } else {
03472 rsbac_printk(KERN_WARNING "do_read_lol_list(): converting list version %u of file %s on device %02u:%02u to version %u!\n",
03473 list_info_p->version,
03474 name,
03475 RSBAC_MAJOR(list->device),
03476 RSBAC_MINOR(list->device),
03477 list->info.version);
03478 }
03479 } else {
03480
03481 if ((list_info_p->desc_size != list->info.desc_size)
03482 || (list_info_p->data_size != list->info.data_size)
03483 || (list_info_p->subdesc_size !=
03484 list->info.subdesc_size)
03485 || (list_info_p->subdata_size !=
03486 list->info.subdata_size)
03487 ) {
03488 if (timeout) {
03489 rsbac_printk(KERN_WARNING "do_read_lol_list(): accessing timed out list %s with wrong desc or data size(s), ignoring old contents!\n",
03490 name);
03491 goto end_read;
03492 } else {
03493 rsbac_printk(KERN_WARNING "do_read_lol_list(): desc or data size mismatch on list %s!\n",
03494 name);
03495 err = -RSBAC_EINVALIDLIST;
03496 goto end_read;
03497 }
03498 }
03499 }
03500
03501
03502 set_fs(KERNEL_DS);
03503 tmperr = file_p->f_op->read(file_p,
03504 (__u8 *) & list_count,
03505 sizeof(list_count), &file_p->f_pos);
03506 set_fs(oldfs);
03507
03508 if (tmperr < sizeof(list_count)) {
03509 rsbac_printk(KERN_WARNING "do_read_lol_list(): list count read error from file %s!\n",
03510 name);
03511 err = -RSBAC_EREADFAILED;
03512 goto end_read;
03513 }
03514
03515
03516 old_buf =
03517 rsbac_kmalloc(list_info_p->desc_size + list_info_p->data_size);
03518 if (!old_buf) {
03519 rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
03520 err = -RSBAC_ENOMEM;
03521 goto end_read;
03522 }
03523 new_buf =
03524 rsbac_kmalloc(list->info.desc_size + list->info.data_size);
03525 if (!new_buf) {
03526 rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
03527 rsbac_kfree(old_buf);
03528 err = -RSBAC_ENOMEM;
03529 goto end_read;
03530 }
03531 old_subbuf =
03532 rsbac_kmalloc(list_info_p->subdesc_size +
03533 list_info_p->subdata_size);
03534 if (!old_subbuf) {
03535 rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
03536 rsbac_kfree(old_buf);
03537 rsbac_kfree(new_buf);
03538 err = -RSBAC_ENOMEM;
03539 goto end_read;
03540 }
03541 new_subbuf =
03542 rsbac_kmalloc(list->info.subdesc_size +
03543 list->info.subdata_size);
03544 if (!new_subbuf) {
03545 rsbac_printk(KERN_WARNING "do_read_lol_list(): cannot allocate memory!\n");
03546 rsbac_kfree(old_buf);
03547 rsbac_kfree(new_buf);
03548 rsbac_kfree(old_subbuf);
03549 err = -RSBAC_ENOMEM;
03550 goto end_read;
03551 }
03552
03553 if (list_info_p->data_size)
03554 old_data = old_buf + list_info_p->desc_size;
03555 else
03556 old_data = NULL;
03557 if (list->info.data_size)
03558 new_data = new_buf + list->info.desc_size;
03559 else
03560 new_data = NULL;
03561 if (list_info_p->subdata_size)
03562 old_subdata = old_subbuf + list_info_p->subdesc_size;
03563 else
03564 old_subdata = NULL;
03565 if (list->info.subdata_size)
03566 new_subdata = new_subbuf + list->info.subdesc_size;
03567 else
03568 new_subdata = NULL;
03569
03570
03571 do {
03572 set_fs(KERNEL_DS);
03573 tmperr = file_p->f_op->read(file_p,
03574 (char *) &max_age,
03575 sizeof(max_age),
03576 &file_p->f_pos);
03577 set_fs(oldfs);
03578 if (conv) {
03579 set_fs(KERNEL_DS);
03580 tmperr = file_p->f_op->read(file_p,
03581 old_buf,
03582 list_info_p->
03583 desc_size +
03584 list_info_p->data_size,
03585 &file_p->f_pos);
03586 set_fs(oldfs);
03587 if (tmperr > 0) {
03588 converr = conv(old_buf, old_data,
03589 new_buf, new_data);
03590 if (converr)
03591 tmperr = converr;
03592 }
03593 } else {
03594 set_fs(KERNEL_DS);
03595 tmperr = file_p->f_op->read(file_p,
03596 new_buf,
03597 list->info.desc_size +
03598 list->info.data_size,
03599 &file_p->f_pos);
03600 set_fs(oldfs);
03601 }
03602
03603 if (tmperr > 0) {
03604
03605 rsbac_write_lock(&list->lock, &flags);
03606 item_p =
03607 add_lol_item(list, max_age, new_buf, new_data);
03608
03609 rsbac_write_unlock(&list->lock, &flags);
03610 if (!item_p) {
03611 err = -RSBAC_ENOMEM;
03612 goto end_read_free;
03613 }
03614 read_count++;
03615
03616
03617
03618 set_fs(KERNEL_DS);
03619 tmperr = file_p->f_op->read(file_p,
03620 (__u8 *) & sublen,
03621 sizeof(sublen),
03622 &file_p->f_pos);
03623 set_fs(oldfs);
03624
03625 if (tmperr > 0) {
03626 for (i = 0; i < sublen; i++) {
03627 set_fs(KERNEL_DS);
03628 tmperr = file_p->f_op->read(file_p,
03629 (char
03630 *)
03631 &max_age,
03632 sizeof
03633 (max_age),
03634 &file_p->
03635 f_pos);
03636 set_fs(oldfs);
03637 if (subconv) {
03638 set_fs(KERNEL_DS);
03639 tmperr =
03640 file_p->f_op->
03641 read(file_p,
03642 old_subbuf,
03643 list_info_p->
03644 subdesc_size +
03645 list_info_p->
03646 subdata_size,
03647 &file_p->f_pos);
03648 set_fs(oldfs);
03649 if (tmperr > 0) {
03650 converr =
03651 subconv
03652 (old_subbuf,
03653 old_subdata,
03654 new_subbuf,
03655 new_subdata);
03656 if (converr)
03657 tmperr =
03658 converr;
03659 }
03660 } else {
03661 set_fs(KERNEL_DS);
03662 tmperr =
03663 file_p->f_op->
03664 read(file_p,
03665 new_subbuf,
03666 list->info.
03667 subdesc_size +
03668 list->info.
03669 subdata_size,
03670 &file_p->f_pos);
03671 set_fs(oldfs);
03672 }
03673 if (tmperr > 0) {
03674
03675 rsbac_write_lock(&list->
03676 lock,
03677 &flags);
03678 if (!add_lol_subitem
03679 (list, item_p, max_age,
03680 new_subbuf,
03681 new_subdata)) {
03682 rsbac_printk
03683 (KERN_WARNING
03684 "do_read_lol_list(): could not add subitem!\n");
03685 i = sublen;
03686 tmperr = -1;
03687 }
03688
03689 rsbac_write_unlock(&list->
03690 lock,
03691 &flags);
03692 } else {
03693 i = sublen;
03694 tmperr = -1;
03695 }
03696 }
03697 }
03698 }
03699 }
03700 while (tmperr > 0);
03701
03702 if (tmperr < 0) {
03703 rsbac_printk(KERN_WARNING "do_read_lol_list(): read error from file %s!\n",
03704 name);
03705 err = -RSBAC_EREADFAILED;
03706 }
03707
03708 if (read_count != list_count) {
03709 rsbac_printk(KERN_WARNING "do_read_lol_list(): read %lu, expected %u items from file %s!\n",
03710 read_count, list_count, name);
03711 err = -RSBAC_EREADFAILED;
03712 }
03713
03714 end_read_free:
03715 rsbac_kfree(old_buf);
03716 rsbac_kfree(new_buf);
03717 rsbac_kfree(old_subbuf);
03718 rsbac_kfree(new_subbuf);
03719
03720 end_read:
03721 rsbac_pr_debug(lists, "%lu entries read.\n", read_count);
03722
03723 rsbac_read_close(file_p);
03724 rsbac_kfree(list_info_p);
03725 rsbac_kfree(file_p);
03726 return err;
03727 }
03728
03729 static int read_lol_list(struct rsbac_list_lol_reg_item_t *list)
03730 {
03731 int res;
03732 u_int flags;
03733
03734 flags = list->flags;
03735 list->flags |= RSBAC_LIST_NO_MAX;
03736 res = do_read_lol_list(list, list->name);
03737 if((res == -RSBAC_ENOTFOUND) && list->old_name_base[0]) {
03738 char name[RSBAC_MAXNAMELEN];
03739 int i;
03740
03741 rsbac_printk(KERN_INFO "read_lol_list(): list %s on device %02u:%02u not found, trying numbered lists 0 to %u with old name base '%s'\n",
03742 list->name, MAJOR(list->device), MINOR(list->device), RSBAC_LIST_LOL_MAX_OLD_HASH-1, list->old_name_base);
03743 for (i=0; i<RSBAC_LIST_LOL_MAX_OLD_HASH; i++) {
03744 sprintf(name, "%s%u", list->old_name_base, i);
03745 res = do_read_lol_list(list, name);
03746 if(res && (res != -RSBAC_ENOTFOUND))
03747 return res;
03748 }
03749 list->dirty = TRUE;
03750 }
03751 list->flags = flags;
03752 return res;
03753 }
03754
03755
03756 #ifndef CONFIG_RSBAC_NO_WRITE
03757 int check_buffer(struct rsbac_list_buffer_t ** buffer_pp, u_int size)
03758 {
03759 if((*buffer_pp)->len + size <= RSBAC_LIST_BUFFER_DATA_SIZE)
03760 return 0;
03761 else {
03762 struct rsbac_list_buffer_t * new_buffer;
03763
03764 new_buffer = rsbac_kmalloc(RSBAC_LIST_BUFFER_SIZE);
03765 if(!new_buffer)
03766 return -RSBAC_ENOMEM;
03767 rsbac_pr_debug(write, "Added a buffer\n");
03768 new_buffer->next = NULL;
03769 new_buffer->len = 0;
03770 (*buffer_pp)->next = new_buffer;
03771 *buffer_pp = new_buffer;
03772 return 0;
03773 }
03774 }
03775
03776 void free_buffers(struct rsbac_list_buffer_t * buffer)
03777 {
03778 struct rsbac_list_buffer_t * next;
03779
03780 while(buffer) {
03781 rsbac_pr_debug(write, "Freeing buffer of size %u\n",
03782 buffer->len);
03783 next = buffer->next;
03784 rsbac_kfree(buffer);
03785 buffer = next;
03786 }
03787 }
03788
03789 static int fill_buffer(struct rsbac_list_reg_item_t *list,
03790 struct rsbac_list_write_item_t **write_item_pp)
03791 {
03792 struct rsbac_list_write_item_t *write_item_p;
03793 struct rsbac_list_item_t *current_p;
03794 u_long flags;
03795 struct rsbac_list_buffer_t *buffer = NULL;
03796 rsbac_list_count_t allcount = 0;
03797 rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
03798 rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
03799 int i;
03800
03801 write_item_p = rsbac_kmalloc(sizeof(*write_item_p));
03802 if (!write_item_p) {
03803 *write_item_pp = NULL;
03804 return (-RSBAC_ENOMEM);
03805 }
03806
03807
03808 rsbac_read_lock(&list->lock, &flags);
03809
03810 write_item_p->prev = NULL;
03811 write_item_p->next = NULL;
03812 write_item_p->list = list;
03813 write_item_p->buffer = NULL;
03814 strncpy(write_item_p->name, list->name, RSBAC_LIST_MAX_FILENAME);
03815 write_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
03816 write_item_p->device = list->device;
03817
03818 for (i=0; i<list->nr_hashes; i++)
03819 allcount += list->hashed[i].count;
03820 buffer = rsbac_kmalloc(RSBAC_LIST_BUFFER_SIZE);
03821 if (!buffer) {
03822
03823 rsbac_read_unlock(&list->lock, &flags);
03824 rsbac_kfree(write_item_p);
03825 *write_item_pp = NULL;
03826 return (-RSBAC_ENOMEM);
03827 }
03828 write_item_p->buffer = buffer;
03829 buffer->len = 0;
03830 buffer->next = NULL;
03831
03832 memcpy(buffer->data, &list_version, sizeof(list_version));
03833 buffer->len = sizeof(list_version);
03834
03835 memcpy(buffer->data + buffer->len,
03836 ×tamp, sizeof(timestamp));
03837 buffer->len += sizeof(timestamp);
03838
03839 memcpy(buffer->data + buffer->len,
03840 &list->info, sizeof(list->info));
03841 buffer->len += sizeof(list->info);
03842
03843 memcpy(buffer->data + buffer->len,
03844 &list->lastchange, sizeof(list->lastchange));
03845 buffer->len += sizeof(list->lastchange);
03846
03847 memcpy(buffer->data + buffer->len,
03848 &allcount, sizeof(allcount));
03849 buffer->len += sizeof(allcount);
03850
03851 for (i=0; i<list->nr_hashes; i++) {
03852 current_p = list->hashed[i].head;
03853 while (current_p) {
03854 if (check_buffer(&buffer, sizeof(current_p->max_age) + list->info.desc_size + list->info.data_size)) {
03855
03856 rsbac_read_unlock(&list->lock, &flags);
03857 free_buffers(write_item_p->buffer);
03858 rsbac_kfree(write_item_p);
03859 *write_item_pp = NULL;
03860 return (-RSBAC_ENOMEM);
03861 }
03862 memcpy(buffer->data + buffer->len,
03863 ¤t_p->max_age, sizeof(current_p->max_age));
03864 buffer->len += sizeof(current_p->max_age);
03865 memcpy(buffer->data + buffer->len,
03866 ((char *) current_p) + sizeof(*current_p),
03867 list->info.desc_size + list->info.data_size);
03868 buffer->len += list->info.desc_size + list->info.data_size;
03869 current_p = current_p->next;
03870 }
03871 }
03872
03873 *write_item_pp = write_item_p;
03874
03875
03876 rsbac_read_unlock(&list->lock, &flags);
03877
03878 return 0;
03879 }
03880
03881 static int rsbac_list_write_buffers(struct rsbac_list_write_head_t write_head,
03882 rsbac_boolean_t need_lock)
03883 {
03884 struct file *file_p;
03885 int count = 0;
03886 mm_segment_t oldfs;
03887 u_int written;
03888 u_long all_written;
03889 u_long bytes;
03890 u_int bufcount;
03891 int tmperr = 0;
03892 struct rsbac_list_buffer_t * buffer;
03893 struct rsbac_list_write_item_t *write_item_p;
03894 struct rsbac_list_write_item_t *next_item_p;
03895
03896 write_item_p = write_head.head;
03897 file_p = rsbac_kmalloc(sizeof(*file_p));
03898 if (!file_p) {
03899 count = -RSBAC_ENOMEM;
03900 goto out_free_all;
03901 }
03902 while (write_item_p) {
03903 rsbac_pr_debug(write, "write list %s on device %02u:%02u.\n",
03904 write_item_p->name,
03905 RSBAC_MAJOR(write_item_p->device),
03906 RSBAC_MINOR(write_item_p->device));
03907 if (need_lock)
03908 lock_kernel();
03909
03910 if ((tmperr = rsbac_write_open(write_item_p->name,
03911 file_p,
03912 write_item_p->device))) {
03913 if (tmperr != -RSBAC_ENOTWRITABLE) {
03914 rsbac_printk(KERN_WARNING "rsbac_list_write_buffers(): opening file %s on device %02u:%02u failed with error %i!\n",
03915 write_item_p->name,
03916 RSBAC_MAJOR(write_item_p->
03917 device),
03918 RSBAC_MINOR(write_item_p->
03919 device), tmperr);
03920 }
03921 count = tmperr;
03922 if(need_lock)
03923 unlock_kernel();
03924 goto out_free_all;
03925 }
03926
03927
03928
03929
03930 oldfs = get_fs();
03931 set_fs(KERNEL_DS);
03932
03933 buffer = write_item_p->buffer;
03934 all_written = 0;
03935 bufcount = 0;
03936 while (buffer && (tmperr >= 0)) {
03937 rsbac_pr_debug(write, "Writing list %s, buffer %u with size %u\n",
03938 write_item_p->name, bufcount, buffer->len);
03939 bufcount++;
03940 written = 0;
03941 while ((written < buffer->len) && (tmperr >= 0)) {
03942 bytes = buffer->len - written;
03943 tmperr = file_p->f_op->write(file_p,
03944 buffer->data + written,
03945 bytes,
03946 &file_p->f_pos);
03947 if (tmperr > 0) {
03948 written += tmperr;
03949 }
03950 }
03951 all_written += written;
03952 buffer = buffer->next;
03953 }
03954
03955
03956 set_fs(oldfs);
03957
03958 rsbac_write_close(file_p);
03959 if (need_lock)
03960 unlock_kernel();
03961 if (tmperr < 0) {
03962 rsbac_printk(KERN_WARNING "rsbac_list_write_buffers(): write error %i on device %02u:%02u file %s!\n",
03963 tmperr,
03964 RSBAC_MAJOR(write_item_p->device),
03965 RSBAC_MINOR(write_item_p->device),
03966 write_item_p->name);
03967 count = tmperr;
03968 goto out_free_all;
03969 } else
03970 count++;
03971
03972 rsbac_pr_debug(write, "%lu bytes from %u buffers written.\n",
03973 all_written, bufcount);
03974
03975 free_buffers(write_item_p->buffer);
03976 next_item_p = write_item_p->next;
03977 rsbac_kfree(write_item_p);
03978 write_item_p = next_item_p;
03979 }
03980
03981 rsbac_kfree(file_p);
03982 return count;
03983
03984 out_free_all:
03985
03986 while(write_item_p)
03987 {
03988 if(write_item_p->list->self == write_item_p->list)
03989 write_item_p->list->dirty = TRUE;
03990 free_buffers(write_item_p->buffer);
03991 next_item_p = write_item_p->next;
03992 rsbac_kfree(write_item_p);
03993 write_item_p = next_item_p;
03994 }
03995 if(file_p)
03996 rsbac_kfree(file_p);
03997 return count;
03998 }
03999
04000 static int fill_lol_buffer(struct rsbac_list_lol_reg_item_t *list,
04001 struct rsbac_list_lol_write_item_t
04002 **write_item_pp)
04003 {
04004 struct rsbac_list_lol_write_item_t *write_item_p;
04005 struct rsbac_list_lol_item_t *current_p;
04006 struct rsbac_list_item_t *sub_p;
04007 u_long flags;
04008 struct rsbac_list_buffer_t *buffer = NULL;
04009 rsbac_list_count_t allcount = 0;
04010 rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
04011 rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
04012 int i;
04013
04014 write_item_p = rsbac_kmalloc(sizeof(*write_item_p));
04015 if (!write_item_p) {
04016 *write_item_pp = NULL;
04017 return (-RSBAC_ENOMEM);
04018 }
04019
04020 rsbac_pr_debug(write, "Filling buffers for list of lists %s\n",
04021 list->name);
04022 rsbac_read_lock(&list->lock, &flags);
04023
04024
04025 write_item_p->prev = NULL;
04026 write_item_p->next = NULL;
04027 write_item_p->list = list;
04028 write_item_p->buffer = NULL;
04029 strncpy(write_item_p->name, list->name, RSBAC_LIST_MAX_FILENAME);
04030 write_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
04031 write_item_p->device = list->device;
04032
04033 for (i=0; i<list->nr_hashes; i++)
04034 allcount += list->hashed[i].count;
04035 buffer = rsbac_kmalloc(RSBAC_LIST_BUFFER_SIZE);
04036 if (!buffer) {
04037
04038 rsbac_read_unlock(&list->lock, &flags);
04039 rsbac_kfree(write_item_p);
04040 *write_item_pp = NULL;
04041 return (-RSBAC_ENOMEM);
04042 }
04043 write_item_p->buffer = buffer;
04044 buffer->len = 0;
04045 buffer->next = NULL;
04046
04047 memcpy(buffer->data, (char *) &list_version, sizeof(list_version));
04048 buffer->len = sizeof(list_version);
04049
04050 memcpy(buffer->data + buffer->len,
04051 (char *) ×tamp, sizeof(timestamp));
04052 buffer->len += sizeof(timestamp);
04053
04054 memcpy(buffer->data + buffer->len,
04055 (char *) &list->info, sizeof(list->info));
04056 buffer->len += sizeof(list->info);
04057
04058 memcpy(buffer->data + buffer->len,
04059 (char *) &list->lastchange, sizeof(list->lastchange));
04060 buffer->len += sizeof(list->lastchange);
04061
04062 memcpy(buffer->data + buffer->len,
04063 (char *) &allcount, sizeof(allcount));
04064 buffer->len += sizeof(allcount);
04065
04066 for (i=0; i<list->nr_hashes; i++) {
04067 current_p = list->hashed[i].head;
04068 while (current_p) {
04069 if (check_buffer(&buffer, sizeof(current_p->max_age)
04070 + list->info.desc_size
04071 + list->info.data_size
04072 + sizeof(current_p->count))) {
04073
04074 rsbac_read_unlock(&list->lock, &flags);
04075 free_buffers(write_item_p->buffer);
04076 rsbac_kfree(write_item_p);
04077 *write_item_pp = NULL;
04078 return (-RSBAC_ENOMEM);
04079 }
04080 memcpy(buffer->data + buffer->len,
04081 ¤t_p->max_age, sizeof(current_p->max_age));
04082 buffer->len += sizeof(current_p->max_age);
04083 memcpy(buffer->data + buffer->len,
04084 ((char *) current_p) + sizeof(*current_p),
04085 list->info.desc_size + list->info.data_size);
04086 buffer->len += list->info.desc_size + list->info.data_size;
04087 memcpy(buffer->data + buffer->len,
04088 ¤t_p->count, sizeof(current_p->count));
04089 buffer->len += sizeof(current_p->count);
04090
04091 sub_p = current_p->head;
04092 while (sub_p) {
04093 if (check_buffer(&buffer, sizeof(sub_p->max_age)
04094 + list->info.subdesc_size
04095 + list->info.subdata_size)) {
04096
04097 rsbac_read_unlock(&list->lock, &flags);
04098 free_buffers(write_item_p->buffer);
04099 rsbac_kfree(write_item_p);
04100 *write_item_pp = NULL;
04101 return (-RSBAC_ENOMEM);
04102 }
04103 memcpy(buffer->data + buffer->len,
04104 &sub_p->max_age, sizeof(sub_p->max_age));
04105 buffer->len += sizeof(sub_p->max_age);
04106 memcpy(buffer->data + buffer->len,
04107 ((char *) sub_p) + sizeof(*sub_p),
04108 list->info.subdesc_size +
04109 list->info.subdata_size);
04110 buffer->len +=
04111 list->info.subdesc_size +
04112 list->info.subdata_size;
04113 sub_p = sub_p->next;
04114 }
04115 current_p = current_p->next;
04116 }
04117 }
04118 *write_item_pp = write_item_p;
04119
04120
04121 rsbac_read_unlock(&list->lock, &flags);
04122
04123 return 0;
04124 }
04125
04126 static int rsbac_list_write_lol_buffers(struct rsbac_list_lol_write_head_t
04127 write_head,
04128 rsbac_boolean_t need_lock)
04129 {
04130 struct file *file_p;
04131 int count = 0;
04132 mm_segment_t oldfs;
04133 u_long written;
04134 u_long all_written;
04135 u_long bytes;
04136 u_int bufcount;
04137 int tmperr = 0;
04138 struct rsbac_list_buffer_t * buffer;
04139 struct rsbac_list_lol_write_item_t *write_item_p;
04140 struct rsbac_list_lol_write_item_t *next_item_p;
04141
04142 write_item_p = write_head.head;
04143 file_p = rsbac_kmalloc(sizeof(*file_p));
04144 if (!file_p) {
04145 count = -RSBAC_ENOMEM;
04146 goto out_free_all;
04147 }
04148 while (write_item_p) {
04149 rsbac_pr_debug(write, "write list of lists %s on device %02u:%02u.\n",
04150 write_item_p->name,
04151 RSBAC_MAJOR(write_item_p->device),
04152 RSBAC_MINOR(write_item_p->device));
04153 if (need_lock)
04154 lock_kernel();
04155
04156 if ((tmperr = rsbac_write_open(write_item_p->name,
04157 file_p,
04158 write_item_p->device))) {
04159 if (tmperr != -RSBAC_ENOTWRITABLE) {
04160 rsbac_printk(KERN_WARNING "rsbac_list_write_lol_buffers(): opening file %s on device %02u:%02u failed with error %i!\n",
04161 write_item_p->name,
04162 RSBAC_MAJOR(write_item_p->
04163 device),
04164 RSBAC_MINOR(write_item_p->
04165 device), tmperr);
04166 }
04167 if (need_lock)
04168 unlock_kernel();
04169 goto out_free_all;
04170 }
04171
04172
04173
04174
04175 oldfs = get_fs();
04176 set_fs(KERNEL_DS);
04177
04178 buffer = write_item_p->buffer;
04179 all_written = 0;
04180 bufcount = 0;
04181 while (buffer && (tmperr >= 0)) {
04182 rsbac_pr_debug(write, "Writing list of lists %s, buffer %u with size %u\n",
04183 write_item_p->name, bufcount, buffer->len);
04184 bufcount++;
04185 written = 0;
04186 while ((written < buffer->len) && (tmperr >= 0)) {
04187 bytes = buffer->len - written;
04188 tmperr = file_p->f_op->write(file_p,
04189 buffer->data + written,
04190 bytes,
04191 &file_p->f_pos);
04192 if (tmperr > 0) {
04193 written += tmperr;
04194 }
04195 }
04196 all_written += written;
04197 buffer = buffer->next;
04198 }
04199
04200
04201 set_fs(oldfs);
04202
04203 rsbac_write_close(file_p);
04204
04205 if (need_lock)
04206 unlock_kernel();
04207
04208 if (tmperr < 0) {
04209 rsbac_printk(KERN_WARNING "rsbac_list_write_lol_buffers(): write error %i on device %02u:%02u file %s!\n",
04210 tmperr,
04211 RSBAC_MAJOR(write_item_p->device),
04212 RSBAC_MINOR(write_item_p->device),
04213 write_item_p->name);
04214 count = tmperr;
04215 goto out_free_all;
04216 } else
04217 count++;
04218
04219 rsbac_pr_debug(write, "%lu bytes from %u buffers written.\n",
04220 all_written, bufcount);
04221 free_buffers(write_item_p->buffer);
04222 next_item_p = write_item_p->next;
04223 rsbac_kfree(write_item_p);
04224 write_item_p = next_item_p;
04225 }
04226
04227 rsbac_kfree(file_p);
04228 return count;
04229
04230 out_free_all:
04231
04232 while(write_item_p)
04233 {
04234 if(write_item_p->list->self == write_item_p->list)
04235 write_item_p->list->dirty = TRUE;
04236 free_buffers(write_item_p->buffer);
04237 next_item_p = write_item_p->next;
04238 rsbac_kfree(write_item_p);
04239 write_item_p = next_item_p;
04240 }
04241 if(file_p)
04242 rsbac_kfree(file_p);
04243 return count;
04244 }
04245 #endif
04246
04247
04248
04249
04250
04251
04252 #if defined(CONFIG_RSBAC_PROC)
04253 static int
04254 lists_proc_info(char *buffer, char **start, off_t offset, int length)
04255 {
04256 int len = 0;
04257 off_t pos = 0;
04258 off_t begin = 0;
04259 union rsbac_target_id_t rsbac_target_id;
04260 union rsbac_attribute_value_t rsbac_attribute_value;
04261 struct rsbac_list_reg_item_t *item_p;
04262 struct rsbac_list_lol_reg_item_t *lol_item_p;
04263 u_long flags;
04264 int i;
04265 u_long tmp_count;
04266
04267 if (!rsbac_is_initialized())
04268 return (-ENOSYS);
04269
04270 rsbac_pr_debug(aef, "calling ADF\n");
04271 rsbac_target_id.scd = ST_rsbac;
04272 rsbac_attribute_value.dummy = 0;
04273 if (!rsbac_adf_request(R_GET_STATUS_DATA,
04274 current->pid,
04275 T_SCD,
04276 rsbac_target_id,
04277 A_none, rsbac_attribute_value)) {
04278 return -EPERM;
04279 }
04280
04281 len +=
04282 sprintf(buffer,
04283 "Generic Lists Status\n--------------------\nMaximum number of hashes per list/list of lists is %u/%u\n",
04284 rsbac_list_max_hashes, rsbac_list_lol_max_hashes);
04285 #ifdef CONFIG_RSBAC_LIST_TRANS
04286 if (rsbac_list_count(ta_handle) > 0) {
04287 int list_count;
04288 rsbac_list_ta_number_t *desc_array;
04289 struct rsbac_list_ta_data_t data;
04290
04291 len += sprintf(buffer + len, "\nTransactions active:\n\n");
04292 pos = begin + len;
04293 if (pos < offset) {
04294 len = 0;
04295 begin = pos;
04296 }
04297 if (pos > offset + length)
04298 goto out;
04299
04300 list_count =
04301 rsbac_list_get_all_desc(ta_handle,
04302 (void **) &desc_array);
04303 if (list_count > 0) {
04304 int i;
04305 rsbac_time_t now = RSBAC_CURRENT_TIME;
04306
04307 for (i = 0; i < list_count; i++) {
04308 if (!rsbac_list_get_data
04309 (ta_handle, &desc_array[i], &data)) {
04310 len +=
04311 sprintf(buffer + len,
04312 "%u (ttl %is)\n",
04313 desc_array[i],
04314 data.timeout - now);
04315 pos = begin + len;
04316 if (pos < offset) {
04317 len = 0;
04318 begin = pos;
04319 }
04320 if (pos > offset + length)
04321 goto out;
04322 }
04323 }
04324 rsbac_vfree(desc_array);
04325 }
04326
04327 len +=
04328 sprintf(buffer + len,
04329 "\nLists in Transaction\n--------------------\nName\t\tdevice\thash\tta\t count\n");
04330 pos = begin + len;
04331 if (pos < offset) {
04332 len = 0;
04333 begin = pos;
04334 }
04335 if (pos > offset + length)
04336 goto out;
04337
04338 list_count = 0;
04339 rsbac_read_lock(®_head.lock, &flags);
04340 item_p = reg_head.head;
04341 while (item_p) {
04342 for (i=0; i<item_p->nr_hashes; i++) {
04343 if (item_p->hashed[i].ta_copied) {
04344 len +=
04345 sprintf(buffer + len,
04346 "%-16s%02u:%02u\t%u\t%10u\t%u\n",
04347 item_p->name,
04348 RSBAC_MAJOR(item_p->device),
04349 RSBAC_MINOR(item_p->device),
04350 i,
04351 item_p->hashed[i].ta_copied,
04352 item_p->hashed[i].ta_count);
04353 pos = begin + len;
04354 if (pos < offset) {
04355 len = 0;
04356 begin = pos;
04357 }
04358 if (pos > offset + length) {
04359 rsbac_read_unlock(®_head.lock,
04360 &flags);
04361 goto out;
04362 }
04363 list_count++;
04364 }
04365 }
04366 item_p = item_p->next;
04367 }
04368 rsbac_read_unlock(®_head.lock, &flags);
04369
04370 len +=
04371 sprintf(buffer + len,
04372 "\n %u lists in transaction.\n\n", list_count);
04373 pos = begin + len;
04374 if (pos < offset) {
04375 len = 0;
04376 begin = pos;
04377 }
04378 if (pos > offset + length)
04379 goto out;
04380
04381 len +=
04382 sprintf(buffer + len,
04383 "Lists of Lists in Transaction\n-----------------------------\nName\t\tdevice\thash\tta\t count\n");
04384 pos = begin + len;
04385 if (pos < offset) {
04386 len = 0;
04387 begin = pos;
04388 }
04389 if (pos > offset + length)
04390 goto out;
04391
04392 list_count = 0;
04393 rsbac_read_lock(&lol_reg_head.lock, &flags);
04394 lol_item_p = lol_reg_head.head;
04395 while (lol_item_p) {
04396 for (i=0; i<lol_item_p->nr_hashes; i++) {
04397 if (lol_item_p->hashed[i].ta_copied) {
04398 len +=
04399 sprintf(buffer + len,
04400 "%-16s%02u:%02u\t%u\t%10u\t%u\n",
04401 lol_item_p->name,
04402 RSBAC_MAJOR(lol_item_p->
04403 device),
04404 RSBAC_MINOR(lol_item_p->
04405 device),
04406 i,
04407 lol_item_p->hashed[i].ta_copied,
04408 lol_item_p->hashed[i].ta_count);
04409 pos = begin + len;
04410 if (pos < offset) {
04411 len = 0;
04412 begin = pos;
04413 }
04414 if (pos > offset + length) {
04415 rsbac_read_unlock(&lol_reg_head.
04416 lock, &flags);
04417 goto out;
04418 }
04419 list_count++;
04420 }
04421 }
04422 lol_item_p = lol_item_p->next;
04423 }
04424 rsbac_read_unlock(&lol_reg_head.lock, &flags);
04425
04426 len +=
04427 sprintf(buffer + len,
04428 "\n %u lists of lists in transaction.\n\n\n",
04429 list_count);
04430 pos = begin + len;
04431 if (pos < offset) {
04432 len = 0;
04433 begin = pos;
04434 }
04435 if (pos > offset + length)
04436 goto out;
04437 } else
04438 len += sprintf(buffer + len, "No active transaction\n\n");
04439 pos = begin + len;
04440 if (pos < offset) {
04441 len = 0;
04442 begin = pos;
04443 }
04444 if (pos > offset + length)
04445 goto out;
04446 #endif
04447
04448 len +=
04449 sprintf(buffer + len,
04450 "Registered Generic Lists (item size %u + per hash %u)\n------------------------\n",
04451 (int) sizeof(struct rsbac_list_reg_item_t), (int) sizeof(struct rsbac_list_hashed_t));
04452 len +=
04453 sprintf(buffer + len,
04454 "Name\t\tdevice\tcount\tdesc\tdata\tpersist\tnow/dir\tflags\thashes\n");
04455 pos = begin + len;
04456 if (pos < offset) {
04457 len = 0;
04458 begin = pos;
04459 }
04460 if (pos > offset + length)
04461 goto out;
04462
04463 rsbac_read_lock(®_head.lock, &flags);
04464 item_p = reg_head.head;
04465 while (item_p) {
04466 tmp_count = 0;
04467 for (i=0; i<item_p->nr_hashes; i++)
04468 tmp_count += item_p->hashed[i].count;
04469 len +=
04470 sprintf(buffer + len,
04471 "%-16s%02u:%02u\t%lu\t%u\t%u\t%u\t%u/%u\t%u\t%u\n",
04472 item_p->name, RSBAC_MAJOR(item_p->device),
04473 RSBAC_MINOR(item_p->device), tmp_count,
04474 item_p->info.desc_size, item_p->info.data_size,
04475 item_p->flags & RSBAC_LIST_PERSIST,
04476 item_p->no_write,
04477 item_p->dirty & (item_p->
04478 flags & RSBAC_LIST_PERSIST),
04479 item_p->flags,
04480 item_p->nr_hashes);
04481 pos = begin + len;
04482 if (pos < offset) {
04483 len = 0;
04484 begin = pos;
04485 }
04486 if (pos > offset + length) {
04487 rsbac_read_unlock(®_head.lock, &flags);
04488 goto out;
04489 }
04490 item_p = item_p->next;
04491 }
04492 rsbac_read_unlock(®_head.lock, &flags);
04493
04494 len += sprintf(buffer + len, "\n %u lists registered.\n\n",
04495 reg_head.count);
04496 pos = begin + len;
04497 if (pos < offset) {
04498 len = 0;
04499 begin = pos;
04500 }
04501 if (pos > offset + length)
04502 goto out;
04503
04504 len +=
04505 sprintf(buffer + len,
04506 "Registered Generic Lists of Lists (item size %u + per hash %u)\n---------------------------------\n",
04507 (int) sizeof(struct rsbac_list_lol_reg_item_t), (int) sizeof(struct rsbac_list_lol_hashed_t));
04508 len +=
04509 sprintf(buffer + len,
04510 "Name\t\tdevice\tcount\tdesc\tdata\tpersist\tnow/dir\tflags\thashes\n");
04511 pos = begin + len;
04512 if (pos < offset) {
04513 len = 0;
04514 begin = pos;
04515 }
04516 if (pos > offset + length)
04517 goto out;
04518
04519 rsbac_read_lock(&lol_reg_head.lock, &flags);
04520 lol_item_p = lol_reg_head.head;
04521 while (lol_item_p) {
04522 tmp_count = 0;
04523 for (i=0; i<lol_item_p->nr_hashes; i++)
04524 tmp_count += lol_item_p->hashed[i].count;
04525 len +=
04526 sprintf(buffer + len,
04527 "%-16s%02u:%02u\t%lu\t%u+%u\t%u+%u\t%u\t%u/%u\t%u\t%u\n",
04528 lol_item_p->name,
04529 RSBAC_MAJOR(lol_item_p->device),
04530 RSBAC_MINOR(lol_item_p->device),
04531 tmp_count, lol_item_p->info.desc_size,
04532 lol_item_p->info.subdesc_size,
04533 lol_item_p->info.data_size,
04534 lol_item_p->info.subdata_size,
04535 lol_item_p->flags & RSBAC_LIST_PERSIST,
04536 lol_item_p->no_write,
04537 lol_item_p->dirty & (lol_item_p->
04538 flags &
04539 RSBAC_LIST_PERSIST),
04540 lol_item_p->flags,
04541 lol_item_p->nr_hashes);
04542 pos = begin + len;
04543 if (pos < offset) {
04544 len = 0;
04545 begin = pos;
04546 }
04547 if (pos > offset + length) {
04548 rsbac_read_unlock(&lol_reg_head.lock, &flags);
04549 goto out;
04550 }
04551 lol_item_p = lol_item_p->next;
04552 }
04553 rsbac_read_unlock(&lol_reg_head.lock, &flags);
04554
04555 len += sprintf(buffer + len, "\n %u lists of lists registered.\n",
04556 lol_reg_head.count);
04557 pos = begin + len;
04558 if (pos < offset) {
04559 len = 0;
04560 begin = pos;
04561 }
04562 if (pos > offset + length)
04563 goto out;
04564
04565 out:
04566 *start = buffer + (offset - begin);
04567 len -= (offset - begin);
04568
04569 if (len > length)
04570 len = length;
04571 return len;
04572 }
04573
04574 static int
04575 lists_counts_proc_info(char *buffer, char **start, off_t offset, int length)
04576 {
04577 int len = 0;
04578 off_t pos = 0;
04579 off_t begin = 0;
04580 union rsbac_target_id_t rsbac_target_id;
04581 union rsbac_attribute_value_t rsbac_attribute_value;
04582 struct rsbac_list_reg_item_t *item_p;
04583 struct rsbac_list_lol_reg_item_t *lol_item_p;
04584 u_long flags;
04585 int i;
04586
04587 if (!rsbac_is_initialized())
04588 return (-ENOSYS);
04589
04590 rsbac_pr_debug(aef, "calling ADF\n");
04591 rsbac_target_id.scd = ST_rsbac;
04592 rsbac_attribute_value.dummy = 0;
04593 if (!rsbac_adf_request(R_GET_STATUS_DATA,
04594 current->pid,
04595 T_SCD,
04596 rsbac_target_id,
04597 A_none, rsbac_attribute_value)) {
04598 return -EPERM;
04599 }
04600
04601 len +=
04602 sprintf(buffer,
04603 "Generic Lists Status\n--------------------\nMaximum number of hashes per list/list of lists is %u/%u\n\n",
04604 rsbac_list_max_hashes, rsbac_list_lol_max_hashes);
04605 len +=
04606 sprintf(buffer + len,
04607 "Registered Generic Lists (item size %u + per hash %u)\n------------------------\n",
04608 (int) sizeof(struct rsbac_list_reg_item_t), (int) sizeof(struct rsbac_list_hashed_t));
04609 len +=
04610 sprintf(buffer + len,
04611 "Name\t\tdevice\tmaxitem\thashes\tcounts\n");
04612 pos = begin + len;
04613 if (pos < offset) {
04614 len = 0;
04615 begin = pos;
04616 }
04617 if (pos > offset + length)
04618 goto out;
04619
04620 rsbac_read_lock(®_head.lock, &flags);
04621 item_p = reg_head.head;
04622 while (item_p) {
04623 len +=
04624 sprintf(buffer + len,
04625 "%-16s%02u:%02u\t%u\t%u\t",
04626 item_p->name, RSBAC_MAJOR(item_p->device),
04627 RSBAC_MINOR(item_p->device),
04628 item_p->max_items_per_hash,
04629 item_p->nr_hashes);
04630 for (i=0; i<item_p->nr_hashes; i++) {
04631 len += sprintf(buffer + len,
04632 " %u",
04633 item_p->hashed[i].count);
04634 pos = begin + len;
04635 if (pos < offset) {
04636 len = 0;
04637 begin = pos;
04638 }
04639 if (pos > offset + length) {
04640 rsbac_read_unlock(®_head.lock, &flags);
04641 goto out;
04642 }
04643 }
04644 len +=
04645 sprintf(buffer + len,
04646 "\n");
04647 pos = begin + len;
04648 if (pos < offset) {
04649 len = 0;
04650 begin = pos;
04651 }
04652 if (pos > offset + length) {
04653 rsbac_read_unlock(®_head.lock, &flags);
04654 goto out;
04655 }
04656 item_p = item_p->next;
04657 }
04658 rsbac_read_unlock(®_head.lock, &flags);
04659
04660 len += sprintf(buffer + len, "\n %u lists registered.\n\n",
04661 reg_head.count);
04662 pos = begin + len;
04663 if (pos < offset) {
04664 len = 0;
04665 begin = pos;
04666 }
04667 if (pos > offset + length)
04668 goto out;
04669
04670 len +=
04671 sprintf(buffer + len,
04672 "Registered Generic Lists of Lists (item size %u + per hash %u)\n---------------------------------\n",
04673 (int) sizeof(struct rsbac_list_lol_reg_item_t), (int) sizeof(struct rsbac_list_lol_hashed_t));
04674 len +=
04675 sprintf(buffer + len,
04676 "Name\t\tdevice\tmaxitem\tmaxsubi\thashes\tcounts\n");
04677 pos = begin + len;
04678 if (pos < offset) {
04679 len = 0;
04680 begin = pos;
04681 }
04682 if (pos > offset + length)
04683 goto out;
04684
04685 rsbac_read_lock(&lol_reg_head.lock, &flags);
04686 lol_item_p = lol_reg_head.head;
04687 while (lol_item_p) {
04688 len +=
04689 sprintf(buffer + len,
04690 "%-16s%02u:%02u\t%u\t%u\t%u\t",
04691 lol_item_p->name, RSBAC_MAJOR(lol_item_p->device),
04692 RSBAC_MINOR(lol_item_p->device),
04693 lol_item_p->max_items_per_hash,
04694 lol_item_p->max_subitems,
04695 lol_item_p->nr_hashes);
04696 for (i=0; i<lol_item_p->nr_hashes; i++) {
04697 len += sprintf(buffer + len,
04698 " %u",
04699 lol_item_p->hashed[i].count);
04700 pos = begin + len;
04701 if (pos < offset) {
04702 len = 0;
04703 begin = pos;
04704 }
04705 if (pos > offset + length) {
04706 rsbac_read_unlock(&lol_reg_head.lock, &flags);
04707 goto out;
04708 }
04709 }
04710 len +=
04711 sprintf(buffer + len,
04712 "\n");
04713 pos = begin + len;
04714 if (pos < offset) {
04715 len = 0;
04716 begin = pos;
04717 }
04718 if (pos > offset + length) {
04719 rsbac_read_unlock(&lol_reg_head.lock, &flags);
04720 goto out;
04721 }
04722 lol_item_p = lol_item_p->next;
04723 }
04724 rsbac_read_unlock(&lol_reg_head.lock, &flags);
04725
04726 len += sprintf(buffer + len, "\n %u lists of lists registered.\n",
04727 lol_reg_head.count);
04728 pos = begin + len;
04729 if (pos < offset) {
04730 len = 0;
04731 begin = pos;
04732 }
04733 if (pos > offset + length)
04734 goto out;
04735
04736 out:
04737 *start = buffer + (offset - begin);
04738 len -= (offset - begin);
04739
04740 if (len > length)
04741 len = length;
04742 return len;
04743 }
04744
04745
04746 static int backup_proc_read(char *page, char **start, off_t off,
04747 int count, int *eof, void *data)
04748 {
04749 int len = 0;
04750 off_t pos = 0;
04751 off_t begin = 0;
04752 int i;
04753
04754 union rsbac_target_id_t rsbac_target_id;
04755 union rsbac_attribute_value_t rsbac_attribute_value;
04756 struct rsbac_list_reg_item_t *list;
04757 struct rsbac_list_item_t *current_p;
04758 rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
04759 rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
04760 u_long rflags, flags;
04761
04762 if (!rsbac_is_initialized())
04763 return -ENOSYS;
04764
04765 rsbac_pr_debug(aef, "calling ADF\n");
04766 rsbac_target_id.scd = ST_rsbac;
04767 rsbac_attribute_value.dummy = 0;
04768 if (!rsbac_adf_request(R_GET_STATUS_DATA,
04769 current->pid,
04770 T_SCD,
04771 rsbac_target_id,
04772 A_none, rsbac_attribute_value)) {
04773 return -EPERM;
04774 }
04775
04776 rsbac_read_lock(®_head.lock, &rflags);
04777 list = lookup_reg(data);
04778 if (!list) {
04779 rsbac_read_unlock(®_head.lock, &rflags);
04780 return -ENOSYS;
04781 }
04782
04783 rsbac_read_lock(&list->lock, &flags);
04784
04785 memcpy(page, (char *) &list_version, sizeof(list_version));
04786 len = sizeof(list_version);
04787
04788 memcpy(page + len, (char *) ×tamp, sizeof(timestamp));
04789 len += sizeof(timestamp);
04790
04791 memcpy(page + len, (char *) &list->info, sizeof(list->info));
04792 len += sizeof(list->info);
04793 pos = begin + len;
04794 if (pos < off) {
04795 len = 0;
04796 begin = pos;
04797 }
04798 if (pos > off + count) {
04799 goto out;
04800 }
04801
04802
04803 for (i=0; i<list->nr_hashes; i++) {
04804 current_p = list->hashed[i].head;
04805 while (current_p) {
04806 memcpy(page + len,
04807 ((char *) current_p) + sizeof(*current_p),
04808 list->info.desc_size + list->info.data_size);
04809 len += list->info.desc_size + list->info.data_size;
04810 pos = begin + len;
04811 if (pos < off) {
04812 len = 0;
04813 begin = pos;
04814 }
04815 if (pos > off + count) {
04816 goto out;
04817 }
04818 current_p = current_p->next;
04819 }
04820 }
04821
04822 out:
04823
04824 rsbac_read_unlock(&list->lock, &flags);
04825 rsbac_read_unlock(®_head.lock, &rflags);
04826 if (len <= off + count)
04827 *eof = 1;
04828 *start = page + (off - begin);
04829 len -= (off - begin);
04830
04831 if (len > count)
04832 len = count;
04833 return len;
04834 }
04835
04836
04837 static int lol_backup_proc_read(char *page, char **start, off_t off,
04838 int count, int *eof, void *data)
04839 {
04840 int len = 0;
04841 off_t pos = 0;
04842 off_t begin = 0;
04843 int i;
04844
04845 union rsbac_target_id_t rsbac_target_id;
04846 union rsbac_attribute_value_t rsbac_attribute_value;
04847 struct rsbac_list_lol_reg_item_t *list;
04848 struct rsbac_list_lol_item_t *current_p;
04849 struct rsbac_list_item_t *sub_p;
04850 rsbac_version_t list_version = RSBAC_LIST_DISK_VERSION;
04851 rsbac_time_t timestamp = RSBAC_CURRENT_TIME;
04852 u_long rflags, flags;
04853
04854 if (!rsbac_is_initialized())
04855 return (-ENOSYS);
04856
04857 rsbac_pr_debug(aef, "calling ADF\n");
04858 rsbac_target_id.scd = ST_rsbac;
04859 rsbac_attribute_value.dummy = 0;
04860 if (!rsbac_adf_request(R_GET_STATUS_DATA,
04861 current->pid,
04862 T_SCD,
04863 rsbac_target_id,
04864 A_none, rsbac_attribute_value)) {
04865 return -EPERM;
04866 }
04867
04868 rsbac_read_lock(&lol_reg_head.lock, &rflags);
04869 list = lookup_lol_reg(data);
04870 if (!list) {
04871 rsbac_read_unlock(&lol_reg_head.lock, &rflags);
04872 return -ENOSYS;
04873 }
04874
04875 rsbac_read_lock(&list->lock, &flags);
04876
04877 memcpy(page, (char *) &list_version, sizeof(list_version));
04878 len = sizeof(list_version);
04879
04880 memcpy(page + len, (char *) ×tamp, sizeof(timestamp));
04881 len += sizeof(timestamp);
04882
04883 memcpy(page + len, (char *) &list->info, sizeof(list->info));
04884 len += sizeof(list->info);
04885 pos = begin + len;
04886 if (pos < off) {
04887 len = 0;
04888 begin = pos;
04889 }
04890 if (pos > off + count) {
04891 goto out;
04892 }
04893
04894
04895 for (i=0; i<list->nr_hashes; i++) {
04896 current_p = list->hashed[i].head;
04897 while (current_p) {
04898 memcpy(page + len,
04899 ((char *) current_p) + sizeof(*current_p),
04900 list->info.desc_size + list->info.data_size);
04901 len += list->info.desc_size + list->info.data_size;
04902 memcpy(page + len,
04903 ¤t_p->count, sizeof(current_p->count));
04904 len += sizeof(current_p->count);
04905 pos = begin + len;
04906 if (pos < off) {
04907 len = 0;
04908 begin = pos;
04909 }
04910 if (pos > off + count) {
04911 goto out;
04912 }
04913
04914 sub_p = current_p->head;
04915 while (sub_p) {
04916 memcpy(page + len,
04917 ((char *) sub_p) + sizeof(*sub_p),
04918 list->info.subdesc_size +
04919 list->info.subdata_size);
04920 len +=
04921 list->info.subdesc_size +
04922 list->info.subdata_size;
04923 pos = begin + len;
04924 if (pos < off) {
04925 len = 0;
04926 begin = pos;
04927 }
04928 if (pos > off + count) {
04929 goto out;
04930 }
04931 sub_p = sub_p->next;
04932 }
04933 current_p = current_p->next;
04934 }
04935 }
04936
04937 out:
04938
04939 rsbac_read_unlock(&list->lock, &flags);
04940 rsbac_read_unlock(&lol_reg_head.lock, &rflags);
04941 if (len <= off + count)
04942 *eof = 1;
04943 *start = page + (off - begin);
04944 len -= (off - begin);
04945
04946 if (len > count)
04947 len = count;
04948 return len;
04949 }
04950 #endif
04951
04952
04953
04954
04955
04956 int rsbac_list_compare_u32(void * desc1, void * desc2)
04957 {
04958 if( *((__u32*) desc1) < *((__u32*) desc2))
04959 return -1;
04960 return( *((__u32*) desc1) != *((__u32*) desc2));
04961 }
04962
04963 #ifdef CONFIG_RSBAC_INIT_DELAY
04964 int rsbac_list_init(void)
04965 #else
04966 int __init rsbac_list_init(void)
04967 #endif
04968 {
04969 #if defined(CONFIG_RSBAC_LIST_TRANS) || defined(CONFIG_RSBAC_LIST_REPL)
04970 int err;
04971 struct rsbac_list_info_t *list_info_p;
04972 #endif
04973 u_int i;
04974
04975 reg_head.head = NULL;
04976 reg_head.tail = NULL;
04977 reg_head.curr = NULL;
04978 reg_head.lock = RW_LOCK_UNLOCKED;
04979 reg_head.count = 0;
04980
04981 lol_reg_head.head = NULL;
04982 lol_reg_head.tail = NULL;
04983 lol_reg_head.curr = NULL;
04984 lol_reg_head.lock = RW_LOCK_UNLOCKED;
04985 lol_reg_head.count = 0;
04986
04987
04988
04989
04990 if(CONFIG_RSBAC_LIST_MAX_HASHES < RSBAC_LIST_MIN_MAX_HASHES)
04991 rsbac_list_max_hashes = RSBAC_LIST_MIN_MAX_HASHES;
04992 else if (CONFIG_RSBAC_LIST_MAX_HASHES > RSBAC_MAX_KMALLOC / sizeof(struct rsbac_list_hashed_t))
04993 rsbac_list_max_hashes = RSBAC_MAX_KMALLOC / sizeof(struct rsbac_list_hashed_t);
04994 else
04995 rsbac_list_max_hashes = CONFIG_RSBAC_LIST_MAX_HASHES;
04996
04997 i = 1;
04998 while ((i << 1) <= rsbac_list_max_hashes)
04999 i = i << 1;
05000 rsbac_list_max_hashes = i;
05001
05002
05003 if(CONFIG_RSBAC_LIST_MAX_HASHES < RSBAC_LIST_MIN_MAX_HASHES)
05004 rsbac_list_lol_max_hashes = RSBAC_LIST_MIN_MAX_HASHES;
05005 else if (CONFIG_RSBAC_LIST_MAX_HASHES > RSBAC_MAX_KMALLOC / sizeof(struct rsbac_list_lol_hashed_t))
05006 rsbac_list_lol_max_hashes = RSBAC_MAX_KMALLOC / sizeof(struct rsbac_list_lol_hashed_t);
05007 else
05008 rsbac_list_lol_max_hashes = CONFIG_RSBAC_LIST_MAX_HASHES;
05009
05010 i = 1;
05011 while ((i << 1) <= rsbac_list_lol_max_hashes)
05012 i = i << 1;
05013 rsbac_list_lol_max_hashes = i;
05014
05015 list_initialized = TRUE;
05016
05017 #if defined(CONFIG_RSBAC_LIST_TRANS) || defined(CONFIG_RSBAC_LIST_REPL)
05018 list_info_p = kmalloc(sizeof(*list_info_p), GFP_KERNEL);
05019 if (!list_info_p) {
05020 return -ENOMEM;
05021 }
05022 #endif
05023
05024
05025 #if defined(CONFIG_RSBAC_PROC)
05026 {
05027 struct proc_dir_entry *tmp_entry_p;
05028
05029 tmp_entry_p = create_proc_entry(RSBAC_LIST_PROC_NAME,
05030 S_IFREG | S_IRUGO,
05031 proc_rsbac_root_p);
05032 if (tmp_entry_p) {
05033 tmp_entry_p->get_info = lists_proc_info;
05034 }
05035 tmp_entry_p = create_proc_entry(RSBAC_LIST_COUNTS_PROC_NAME,
05036 S_IFREG | S_IRUGO,
05037 proc_rsbac_root_p);
05038 if (tmp_entry_p) {
05039 tmp_entry_p->get_info = lists_counts_proc_info;
05040 }
05041 }
05042 #endif
05043
05044 #ifdef CONFIG_RSBAC_LIST_TRANS
05045 rsbac_printk(KERN_INFO "rsbac_list_init(): Registering transaction list.\n");
05046 list_info_p->version = 1;
05047 list_info_p->key = RSBAC_LIST_TA_KEY;
05048 list_info_p->desc_size = sizeof(rsbac_list_ta_number_t);
05049 list_info_p->data_size = sizeof(struct rsbac_list_ta_data_t);
05050 list_info_p->max_age = 0;
05051 err = rsbac_list_register(RSBAC_LIST_VERSION,
05052 (void **) &ta_handle,
05053 list_info_p,
05054 0,
05055 NULL,
05056 NULL,
05057 NULL, "transactions", RSBAC_AUTO_DEV);
05058 if (err) {
05059 char *tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
05060
05061 if (tmp) {
05062 rsbac_printk(KERN_WARNING "rsbac_list_init(): Registering transaction list failed with error %s\n",
05063 get_error_name(tmp, err));
05064 kfree(tmp);
05065 }
05066 }
05067 #endif
05068
05069 #if defined(CONFIG_RSBAC_LIST_TRANS) || defined(CONFIG_RSBAC_LIST_REPL)
05070 kfree(list_info_p);
05071 #endif
05072
05073 return 0;
05074 }
05075
05076 int rsbac_list_mount(kdev_t kdev)
05077 {
05078 return 0;
05079 }
05080
05081 int rsbac_list_umount(kdev_t kdev)
05082 {
05083 return 0;
05084 }
05085
05086 #ifdef CONFIG_RSBAC_AUTO_WRITE
05087 int rsbac_list_auto_rehash(void);
05088
05089 int rsbac_write_lists(rsbac_boolean_t need_lock)
05090 {
05091 int count = 0;
05092 int subcount = 0;
05093 int error = 0;
05094 struct rsbac_list_reg_item_t *item_p;
05095 struct rsbac_list_lol_reg_item_t *lol_item_p;
05096 u_long lock_flags;
05097 struct rsbac_list_write_head_t write_head;
05098 struct rsbac_list_write_item_t *write_item_p;
05099 struct rsbac_list_lol_write_head_t write_lol_head;
05100 struct rsbac_list_lol_write_item_t *write_lol_item_p;
05101
05102
05103
05104 if (!list_initialized)
05105 return -RSBAC_ENOTINITIALIZED;
05106
05107 #ifdef CONFIG_RSBAC_LIST_TRANS
05108 if (rsbac_list_count(ta_handle) > 0) {
05109 int list_count;
05110 rsbac_list_ta_number_t *desc_array;
05111 struct rsbac_list_ta_data_t data;
05112
05113 list_count =
05114 rsbac_list_get_all_desc(ta_handle,
05115 (void **) &desc_array);
05116 if (list_count > 0) {
05117 int i;
05118 rsbac_time_t now = RSBAC_CURRENT_TIME;
05119
05120 for (i = 0; i < list_count; i++) {
05121 if (!rsbac_list_get_data
05122 (ta_handle, &desc_array[i], &data)) {
05123 if (data.timeout < now) {
05124 rsbac_printk(KERN_WARNING "rsbac_write_lists(): transaction %u timed out, forcing forget\n",
05125 desc_array
05126 [i]);
05127 do_forget(desc_array[i]);
05128 }
05129 }
05130 }
05131 rsbac_vfree(desc_array);
05132 }
05133 }
05134 #endif
05135
05136
05137 write_head.head = NULL;
05138 write_head.tail = NULL;
05139 write_head.count = 0;
05140
05141 rsbac_read_lock(®_head.lock, &lock_flags);
05142 item_p = reg_head.head;
05143 while (item_p) {
05144 if ((item_p->flags & RSBAC_LIST_PERSIST)
05145 && item_p->dirty && !item_p->no_write) {
05146 item_p->dirty = FALSE;
05147
05148 error = fill_buffer(item_p, &write_item_p);
05149 if (!error) {
05150 if (!write_head.head) {
05151 write_head.head = write_item_p;
05152 write_head.tail = write_item_p;
05153 write_head.count = 1;
05154 } else {
05155 write_head.tail->next =
05156 write_item_p;
05157 write_item_p->prev =
05158 write_head.tail;
05159 write_head.tail = write_item_p;
05160 write_head.count++;
05161 }
05162 } else {
05163 if ((error != -RSBAC_ENOTWRITABLE)
05164 && (error != -RSBAC_ENOMEM)
05165 ) {
05166 rsbac_printk(KERN_WARNING "rsbac_write_lists(): fill_buffer() for list %s returned error %i\n",
05167 item_p->name, error);
05168 item_p->dirty = TRUE;
05169 }
05170 }
05171 }
05172 item_p = item_p->next;
05173 }
05174 rsbac_read_unlock(®_head.lock, &lock_flags);
05175
05176 if (write_head.count > 0)
05177 rsbac_pr_debug(write, "%u lists copied to buffers\n",
05178 write_head.count);
05179
05180
05181 if (write_head.count) {
05182 count = rsbac_list_write_buffers(write_head, need_lock);
05183 rsbac_pr_debug(write, "%u lists written to disk\n", count);
05184 }
05185
05186
05187
05188 write_lol_head.head = NULL;
05189 write_lol_head.tail = NULL;
05190 write_lol_head.count = 0;
05191
05192 rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
05193 lol_item_p = lol_reg_head.head;
05194 while (lol_item_p) {
05195 if ((lol_item_p->flags & RSBAC_LIST_PERSIST)
05196 && lol_item_p->dirty && !lol_item_p->no_write) {
05197 lol_item_p->dirty = FALSE;
05198
05199 error = fill_lol_buffer(lol_item_p, &write_lol_item_p);
05200 if (!error) {
05201 if (!write_lol_head.head) {
05202 write_lol_head.head =
05203 write_lol_item_p;
05204 write_lol_head.tail =
05205 write_lol_item_p;
05206 write_lol_head.count = 1;
05207 } else {
05208 write_lol_head.tail->next =
05209 write_lol_item_p;
05210 write_lol_item_p->prev =
05211 write_lol_head.tail;
05212 write_lol_head.tail =
05213 write_lol_item_p;
05214 write_lol_head.count++;
05215 }
05216 } else {
05217 if ((error != -RSBAC_ENOTWRITABLE)
05218 && (error != -RSBAC_ENOMEM))
05219 {
05220 rsbac_printk(KERN_WARNING "rsbac_write_lists(): fill_lol_buffer() for list %s returned error %i\n",
05221 lol_item_p->name,
05222 error);
05223 }
05224 lol_item_p->dirty = TRUE;
05225 }
05226 }
05227 lol_item_p = lol_item_p->next;
05228 }
05229 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
05230
05231 if (write_lol_head.count > 0)
05232 rsbac_pr_debug(write, "%u lists of lists copied to buffers\n",
05233 write_lol_head.count);
05234
05235 if (write_lol_head.count) {
05236 subcount =
05237 rsbac_list_write_lol_buffers(write_lol_head,
05238 need_lock);
05239 count += subcount;
05240 rsbac_pr_debug(write, "%u lists of lists written to disk\n",
05241 subcount);
05242 }
05243 rsbac_pr_debug(write, "%u lists written.\n",
05244 count);
05245
05246 if(jiffies > next_rehash) {
05247 rsbac_list_auto_rehash();
05248 next_rehash = jiffies + (RSBAC_LIST_REHASH_INTERVAL * HZ);
05249 }
05250 return count;
05251 }
05252 #endif
05253
05254
05255 int rsbac_check_lists(int correct)
05256 {
05257 struct rsbac_list_reg_item_t *list;
05258 struct rsbac_list_lol_reg_item_t *lol_list;
05259 struct rsbac_list_item_t *item_p;
05260 struct rsbac_list_item_t *next_item_p;
05261 struct rsbac_list_lol_item_t *lol_item_p;
05262 struct rsbac_list_lol_item_t *next_lol_item_p;
05263 struct rsbac_list_item_t *lol_subitem_p;
05264 struct rsbac_list_item_t *next_lol_subitem_p;
05265 u_long lock_flags, rlock_flags;
05266 u_long tmp_count;
05267 u_long tmp_subcount;
05268 u_long subitem_count;
05269 u_long dirty = 0;
05270 int i;
05271 u_long all_count;
05272
05273 rsbac_pr_debug(lists, "called.\n");
05274 if (!list_initialized)
05275 return -RSBAC_ENOTINITIALIZED;
05276 rsbac_read_lock(®_head.lock, &rlock_flags);
05277 list = reg_head.head;
05278 while (list) {
05279
05280 rsbac_write_lock(&list->lock, &lock_flags);
05281 all_count = 0;
05282 for (i=0; i<list->nr_hashes; i++) {
05283 tmp_count = 0;
05284 item_p = list->hashed[i].head;
05285 while (item_p) {
05286 if ((item_p->max_age
05287 && (item_p->max_age <= RSBAC_CURRENT_TIME)
05288 )
05289 || (list->def_data
05290 && !memcmp(((char *) item_p) +
05291 sizeof(*item_p) +
05292 list->info.desc_size,
05293 list->def_data,
05294 list->info.data_size)
05295 )
05296 ) {
05297 next_item_p = item_p->next;
05298 do_remove_item(list, item_p, i);
05299 item_p = next_item_p;
05300 } else {
05301 tmp_count++;
05302 item_p = item_p->next;
05303 }
05304 }
05305 if (tmp_count != list->hashed[i].count) {
05306 if (correct) {
05307 rsbac_printk(KERN_WARNING "rsbac_check_lists(): correcting count mismatch for list %s hash %u on device %02u:%02u - was %u, counted %lu!\n",
05308 list->name, i,
05309 RSBAC_MAJOR(list->device),
05310 RSBAC_MINOR(list->device),
05311 list->hashed[i].count, tmp_count);
05312 list->hashed[i].count = tmp_count;
05313 } else {
05314 rsbac_printk(KERN_WARNING "rsbac_check_lists(): count mismatch for list %s hash %u on device %02u:%02u - is %u, counted %lu!\n",
05315 list->name, i,
05316 RSBAC_MAJOR(list->device),
05317 RSBAC_MINOR(list->device),
05318 list->hashed[i].count, tmp_count);
05319 }
05320 }
05321 all_count += list->hashed[i].count;
05322 }
05323 rsbac_write_unlock(&list->lock, &lock_flags);
05324 if (list->dirty && (list->flags & RSBAC_LIST_PERSIST)) {
05325 dirty++;
05326 rsbac_pr_debug(lists, "%s on %02u:%02u has %u items (list is dirty)\n",
05327 list->name, RSBAC_MAJOR(list->device),
05328 RSBAC_MINOR(list->device), all_count);
05329 } else
05330 rsbac_pr_debug(lists, "%s on %02u:%02u has %u items\n",
05331 list->name, RSBAC_MAJOR(list->device),
05332 RSBAC_MINOR(list->device), all_count);
05333 list = list->next;
05334 }
05335 rsbac_read_unlock(®_head.lock, &rlock_flags);
05336
05337 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
05338 lol_list = lol_reg_head.head;
05339 while (lol_list) {
05340
05341 rsbac_write_lock(&lol_list->lock, &lock_flags);
05342 all_count = 0;
05343 subitem_count = 0;
05344 for (i=0; i<lol_list->nr_hashes; i++) {
05345 tmp_count = 0;
05346 lol_item_p = lol_list->hashed[i].head;
05347 while (lol_item_p) {
05348 tmp_subcount = 0;
05349 lol_subitem_p = lol_item_p->head;
05350 while (lol_subitem_p) {
05351 if ((lol_subitem_p->max_age
05352 && (lol_subitem_p->max_age <=
05353 RSBAC_CURRENT_TIME)
05354 )
05355 || (lol_list->def_subdata
05356 &&
05357 !memcmp(((char *)
05358 lol_subitem_p) +
05359 sizeof
05360 (*lol_subitem_p) +
05361 lol_list->info.
05362 subdesc_size,
05363 lol_list->
05364 def_subdata,
05365 lol_list->info.
05366 subdata_size)
05367 )
05368 ) {
05369 next_lol_subitem_p =
05370 lol_subitem_p->next;
05371 do_remove_lol_subitem
05372 (lol_item_p,
05373 lol_subitem_p);
05374 lol_subitem_p =
05375 next_lol_subitem_p;
05376 } else {
05377 tmp_subcount++;
05378 lol_subitem_p =
05379 lol_subitem_p->next;
05380 }
05381 }
05382 if (tmp_subcount != lol_item_p->count) {
05383 if (correct) {
05384 rsbac_printk(KERN_WARNING "rsbac_check_lists(): correcting count mismatch for list of lists %s hash %u sublist on %02u:%02u - was %lu, counted %lu!\n",
05385 lol_list->name, i,
05386 RSBAC_MAJOR
05387 (lol_list->
05388 device),
05389 RSBAC_MINOR
05390 (lol_list->
05391 device),
05392 lol_item_p->
05393 count,
05394 tmp_subcount);
05395 lol_item_p->count =
05396 tmp_subcount;
05397 } else {
05398 rsbac_printk(KERN_WARNING "rsbac_check_lists(): count mismatch for list of lists %s hash %u sublist on %02u:%02u - is %lu, counted %lu!\n",
05399 lol_list->name, i,
05400 RSBAC_MAJOR
05401 (lol_list->
05402 device),
05403 RSBAC_MINOR
05404 (lol_list->
05405 device),
05406 lol_item_p->
05407 count,
05408 tmp_subcount);
05409 }
05410 }
05411 if ((lol_item_p->max_age
05412 && (lol_item_p->max_age <= RSBAC_CURRENT_TIME)
05413 )
05414 || (lol_list->def_data
05415 && !lol_item_p->count
05416 && !memcmp(((char *) lol_item_p) +
05417 sizeof(*lol_item_p) +
05418 lol_list->info.desc_size,
05419 lol_list->def_data,
05420 lol_list->info.data_size)
05421 )
05422 || (!lol_list->info.data_size
05423 && (lol_list->flags & RSBAC_LIST_DEF_DATA)
05424 && !lol_item_p->count)
05425 ) {
05426 next_lol_item_p = lol_item_p->next;
05427 do_remove_lol_item(lol_list, lol_item_p, i);
05428 lol_item_p = next_lol_item_p;
05429 } else {
05430 tmp_count++;
05431 subitem_count += lol_item_p->count;
05432 lol_item_p = lol_item_p->next;
05433 }
05434 }
05435 if (tmp_count != lol_list->hashed[i].count) {
05436 if (correct) {
05437 rsbac_printk(KERN_WARNING "rsbac_check_lists(): correcting count mismatch for list of lists %s hash %u on %02u:%02u - was %u, counted %lu!\n",
05438 lol_list->name, i,
05439 RSBAC_MAJOR(lol_list->device),
05440 RSBAC_MINOR(lol_list->device),
05441 lol_list->hashed[i].count, tmp_count);
05442 lol_list->hashed[i].count = tmp_count;
05443 } else {
05444 rsbac_printk(KERN_WARNING "rsbac_check_lists(): count mismatch for list of lists %s hash %u on %02u:%02u - is %u, counted %lu!\n",
05445 lol_list->name, i,
05446 RSBAC_MAJOR(lol_list->device),
05447 RSBAC_MINOR(lol_list->device),
05448 lol_list->hashed[i].count, tmp_count);
05449 }
05450 }
05451 all_count += lol_list->hashed[i].count;
05452 }
05453 rsbac_write_unlock(&lol_list->lock, &lock_flags);
05454 if (lol_list->dirty
05455 && (lol_list->flags & RSBAC_LIST_PERSIST)) {
05456 dirty++;
05457 rsbac_pr_debug(lists, "%s on %02u:%02u has %u items and %lu subitems (list is dirty)\n",
05458 lol_list->name,
05459 RSBAC_MAJOR(lol_list->device),
05460 RSBAC_MINOR(lol_list->device),
05461 all_count, subitem_count);
05462 } else
05463 rsbac_pr_debug(lists, "%s on %02u:%02u has %u items and %lu subitems\n",
05464 lol_list->name,
05465 RSBAC_MAJOR(lol_list->device),
05466 RSBAC_MINOR(lol_list->device),
05467 all_count, subitem_count);
05468 lol_list = lol_list->next;
05469 }
05470 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
05471 return 0;
05472 }
05473
05474 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05475 EXPORT_SYMBOL(rsbac_list_check);
05476 #endif
05477 int rsbac_list_check(rsbac_list_handle_t handle, int correct)
05478 {
05479 struct rsbac_list_reg_item_t *list;
05480 struct rsbac_list_item_t *item_p;
05481 struct rsbac_list_item_t *next_item_p;
05482 u_long lock_flags;
05483 u_long rlock_flags;
05484 u_long tmp_count;
05485 int i;
05486
05487 if (!handle)
05488 return -RSBAC_EINVALIDLIST;
05489 if (!list_initialized)
05490 return -RSBAC_ENOTINITIALIZED;
05491
05492 list = (struct rsbac_list_reg_item_t *) handle;
05493 if (!list || (list->self != list))
05494 return -RSBAC_EINVALIDLIST;
05495
05496 rsbac_read_lock(®_head.lock, &rlock_flags);
05497 rsbac_pr_debug(lists, "checking list %s.\n", list->name);
05498 rsbac_write_lock(&list->lock, &lock_flags);
05499 for (i=0; i<list->nr_hashes; i++) {
05500 tmp_count = 0;
05501 item_p = list->hashed[i].head;
05502 while (item_p) {
05503 if ((item_p->max_age
05504 && (item_p->max_age <= RSBAC_CURRENT_TIME)
05505 )
05506 || (list->def_data
05507 && !memcmp(((char *) item_p) + sizeof(*item_p) +
05508 list->info.desc_size, list->def_data,
05509 list->info.data_size)
05510 )
05511 ) {
05512 next_item_p = item_p->next;
05513 do_remove_item(list, item_p, i);
05514 item_p = next_item_p;
05515 list->dirty = TRUE;
05516 } else {
05517 tmp_count++;
05518 item_p = item_p->next;
05519 }
05520 }
05521 if (tmp_count != list->hashed[i].count) {
05522 if (correct) {
05523 rsbac_printk(KERN_WARNING "rsbac_list_check(): correcting count mismatch for list %s hash %u on device %02u:%02u - was %u, counted %lu!\n",
05524 list->name, i, RSBAC_MAJOR(list->device),
05525 RSBAC_MINOR(list->device),
05526 list->hashed[i].count, tmp_count);
05527 list->hashed[i].count = tmp_count;
05528 list->dirty = TRUE;
05529 } else {
05530 rsbac_printk(KERN_WARNING "rsbac_list_check(): count mismatch for list %s hash %u on device %02u:%02u - is %u, counted %lu!\n",
05531 list->name, i, RSBAC_MAJOR(list->device),
05532 RSBAC_MINOR(list->device),
05533 list->hashed[i].count, tmp_count);
05534 }
05535 }
05536 }
05537 rsbac_write_unlock(&list->lock, &lock_flags);
05538 rsbac_read_unlock(®_head.lock, &rlock_flags);
05539 return 0;
05540 }
05541
05542 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05543 EXPORT_SYMBOL(rsbac_list_lol_check);
05544 #endif
05545 int rsbac_list_lol_check(rsbac_list_handle_t handle, int correct)
05546 {
05547 struct rsbac_list_lol_reg_item_t *lol_list;
05548 struct rsbac_list_lol_item_t *lol_item_p;
05549 struct rsbac_list_lol_item_t *next_lol_item_p;
05550 struct rsbac_list_item_t *lol_subitem_p;
05551 struct rsbac_list_item_t *next_lol_subitem_p;
05552 u_long lock_flags;
05553 u_long rlock_flags;
05554 u_long tmp_count;
05555 u_long tmp_subcount;
05556 int i;
05557
05558 if (!handle)
05559 return -RSBAC_EINVALIDLIST;
05560 if (!list_initialized)
05561 return -RSBAC_ENOTINITIALIZED;
05562
05563 lol_list = (struct rsbac_list_lol_reg_item_t *) handle;
05564 if (!lol_list || (lol_list->self != lol_list))
05565 return -RSBAC_EINVALIDLIST;
05566
05567 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
05568 rsbac_pr_debug(lists, "checking list %s.\n", lol_list->name);
05569 rsbac_write_lock(&lol_list->lock, &lock_flags);
05570 for (i=0; i<lol_list->nr_hashes; i++) {
05571 tmp_count = 0;
05572 lol_item_p = lol_list->hashed[i].head;
05573 while (lol_item_p) {
05574 if ((lol_item_p->max_age
05575 && (lol_item_p->max_age <= RSBAC_CURRENT_TIME)
05576 )
05577 || (lol_list->def_data
05578 && !lol_item_p->count
05579 && !memcmp(((char *) lol_item_p) +
05580 sizeof(*lol_item_p) +
05581 lol_list->info.desc_size,
05582 lol_list->def_data,
05583 lol_list->info.data_size)
05584 )
05585 || (!lol_list->info.data_size
05586 && (lol_list->flags & RSBAC_LIST_DEF_DATA)
05587 && !lol_item_p->count)
05588 ) {
05589 next_lol_item_p = lol_item_p->next;
05590 do_remove_lol_item(lol_list, lol_item_p, i);
05591 lol_item_p = next_lol_item_p;
05592 } else {
05593 tmp_count++;
05594 tmp_subcount = 0;
05595 lol_subitem_p = lol_item_p->head;
05596 while (lol_subitem_p) {
05597 if ((lol_subitem_p->max_age
05598 && (lol_subitem_p->max_age <=
05599 RSBAC_CURRENT_TIME)
05600 )
05601 || (lol_list->def_subdata
05602 && !memcmp(((char *) lol_subitem_p)
05603 +
05604 sizeof(*lol_subitem_p) +
05605 lol_list->info.
05606 subdesc_size,
05607 lol_list->def_subdata,
05608 lol_list->info.
05609 subdata_size)
05610 )
05611 ) {
05612 next_lol_subitem_p =
05613 lol_subitem_p->next;
05614 do_remove_lol_subitem(lol_item_p,
05615 lol_subitem_p);
05616 lol_subitem_p = next_lol_subitem_p;
05617 } else {
05618 tmp_subcount++;
05619 lol_subitem_p =
05620 lol_subitem_p->next;
05621 }
05622 }
05623 if (tmp_subcount != lol_item_p->count) {
05624 if (correct) {
05625 rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): correcting count mismatch for list of lists %s hash %u sublist on %02u:%02u - was %lu, counted %lu!\n",
05626 lol_list->name, i,
05627 RSBAC_MAJOR(lol_list->
05628 device),
05629 RSBAC_MINOR(lol_list->
05630 device),
05631 lol_item_p->count,
05632 tmp_subcount);
05633 lol_item_p->count = tmp_subcount;
05634 } else {
05635 rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): count mismatch for list of lists %s hash %u sublist on %02u:%02u - is %lu, counted %lu!\n",
05636 lol_list->name, i,
05637 RSBAC_MAJOR(lol_list->
05638 device),
05639 RSBAC_MINOR(lol_list->
05640 device),
05641 lol_item_p->count,
05642 tmp_subcount);
05643 }
05644 }
05645 lol_item_p = lol_item_p->next;
05646 }
05647 }
05648 if (tmp_count != lol_list->hashed[i].count) {
05649 if (correct) {
05650 rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): correcting count mismatch for list of lists %s hash %u on %02u:%02u - was %u, counted %lu!\n",
05651 lol_list->name, i,
05652 RSBAC_MAJOR(lol_list->device),
05653 RSBAC_MINOR(lol_list->device),
05654 lol_list->hashed[i].count, tmp_count);
05655 lol_list->hashed[i].count = tmp_count;
05656 } else {
05657 rsbac_printk(KERN_WARNING "rsbac_list_lol_check(): count mismatch for list of lists %s hash %u on %02u:%02u - is %u, counted %lu!\n",
05658 lol_list->name, i,
05659 RSBAC_MAJOR(lol_list->device),
05660 RSBAC_MINOR(lol_list->device),
05661 lol_list->hashed[i].count, tmp_count);
05662 }
05663 }
05664 }
05665 rsbac_write_unlock(&lol_list->lock, &lock_flags);
05666 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
05667 return 0;
05668 }
05669
05670
05671
05672
05673
05674
05675
05676 rsbac_version_t rsbac_list_version(void)
05677 {
05678 return RSBAC_LIST_VERSION;
05679 }
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05720 EXPORT_SYMBOL(rsbac_list_register_hashed);
05721 #endif
05722 int rsbac_list_register_hashed(rsbac_version_t ds_version,
05723 rsbac_list_handle_t * handle_p,
05724 struct rsbac_list_info_t *info_p,
05725 u_int flags,
05726 rsbac_list_compare_function_t * compare,
05727 rsbac_list_get_conv_t * get_conv,
05728 void *def_data, char *name, kdev_t device,
05729 u_int nr_hashes,
05730 rsbac_list_hash_function_t hash_function,
05731 char * old_base_name)
05732 {
05733 struct rsbac_list_reg_item_t *reg_item_p;
05734 struct rsbac_list_reg_item_t *new_reg_item_p;
05735 u_long lock_flags;
05736 int err = 0;
05737
05738 if (ds_version != RSBAC_LIST_VERSION) {
05739 if (name) {
05740 rsbac_printk(KERN_WARNING "rsbac_list_register: wrong ds_version %u for list %s, expected %u!\n",
05741 ds_version, name, RSBAC_LIST_VERSION);
05742 }
05743 return -RSBAC_EINVALIDVERSION;
05744 }
05745 if (!handle_p || !info_p)
05746 return -RSBAC_EINVALIDPOINTER;
05747 *handle_p = NULL;
05748 if (!list_initialized)
05749 return -RSBAC_ENOTINITIALIZED;
05750 if (!info_p->key || !info_p->version || !info_p->desc_size)
05751 return -RSBAC_EINVALIDVALUE;
05752 if (info_p->max_age > RSBAC_LIST_MAX_AGE_LIMIT)
05753 return -RSBAC_EINVALIDVALUE;
05754 if (info_p->desc_size + info_p->data_size >
05755 RSBAC_LIST_MAX_ITEM_SIZE)
05756 return -RSBAC_EINVALIDVALUE;
05757 if (nr_hashes > rsbac_list_max_hashes)
05758 nr_hashes = rsbac_list_max_hashes;
05759 else if (nr_hashes > 2) {
05760 u_int i = 1;
05761
05762 while ((i << 1) <= nr_hashes)
05763 i = i << 1;
05764 nr_hashes = i;
05765 }
05766 if (!hash_function) {
05767 nr_hashes = 1;
05768 flags &= ~RSBAC_LIST_AUTO_HASH_RESIZE;
05769 } else
05770 if (!nr_hashes)
05771 nr_hashes = 1;
05772 if (name) {
05773 struct rsbac_list_lol_reg_item_t *lol_reg_item_p;
05774
05775 rsbac_read_lock(®_head.lock, &lock_flags);
05776 reg_item_p = lookup_reg_name(name, device);
05777 rsbac_read_unlock(®_head.lock, &lock_flags);
05778 if (reg_item_p) {
05779 rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
05780 name, RSBAC_MAJOR(device),
05781 RSBAC_MINOR(device));
05782 return -RSBAC_EEXISTS;
05783 }
05784 rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
05785 lol_reg_item_p = lookup_lol_reg_name(name, device);
05786 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
05787 if (lol_reg_item_p) {
05788 rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
05789 name, RSBAC_MAJOR(device),
05790 RSBAC_MINOR(device));
05791 return -RSBAC_EEXISTS;
05792 }
05793 } else if (flags & RSBAC_LIST_PERSIST) {
05794 rsbac_printk(KERN_WARNING "rsbac_list_register: trial to register persistent list without name.\n");
05795 return -RSBAC_EINVALIDVALUE;
05796 }
05797
05798 if (flags & RSBAC_LIST_PERSIST) {
05799 if (RSBAC_IS_AUTO_DEV(device))
05800 device = rsbac_root_dev;
05801 if (!RSBAC_MAJOR(device))
05802 flags &= ~RSBAC_LIST_PERSIST;
05803 }
05804 rsbac_pr_debug(lists, "registering list %s for device %02u:%02u.\n",
05805 name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
05806 new_reg_item_p =
05807 create_reg(info_p, flags, compare, get_conv, def_data, name,
05808 device, nr_hashes, hash_function, old_base_name);
05809 if (!new_reg_item_p) {
05810 return -RSBAC_ECOULDNOTADDITEM;
05811 }
05812
05813 if ((flags & RSBAC_LIST_PERSIST)
05814 && RSBAC_MAJOR(device)
05815 ) {
05816 rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u.\n",
05817 name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
05818 err = read_list(new_reg_item_p);
05819
05820 if (err == -RSBAC_ENOTFOUND)
05821 err = 0;
05822 else if (err) {
05823 char tmp[RSBAC_MAXNAMELEN];
05824 rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u failed with error %s, unregistering list.\n", name,
05825 RSBAC_MAJOR(device),
05826 RSBAC_MINOR(device),
05827 get_error_name(tmp, err));
05828 clear_reg(new_reg_item_p);
05829 return err;
05830 } else
05831 rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u was successful.\n",
05832 name, RSBAC_MAJOR(device),
05833 RSBAC_MINOR(device));
05834 }
05835
05836 rsbac_write_lock(®_head.lock, &lock_flags);
05837 reg_item_p = add_reg(new_reg_item_p);
05838 rsbac_write_unlock(®_head.lock, &lock_flags);
05839 if (!reg_item_p) {
05840 rsbac_printk(KERN_WARNING "rsbac_list_register: inserting list %s failed!\n",
05841 name);
05842
05843 clear_reg(new_reg_item_p);
05844 return -RSBAC_ECOULDNOTADDITEM;
05845 }
05846
05847
05848 #if defined(CONFIG_RSBAC_PROC)
05849
05850 if (flags & RSBAC_LIST_BACKUP) {
05851 reg_item_p->proc_entry_p =
05852 create_proc_entry(reg_item_p->name, S_IFREG | S_IRUGO,
05853 proc_rsbac_backup_p);
05854 if (reg_item_p->proc_entry_p) {
05855 reg_item_p->proc_entry_p->read_proc =
05856 backup_proc_read;
05857 reg_item_p->proc_entry_p->data = reg_item_p;
05858 }
05859 } else {
05860 reg_item_p->proc_entry_p = NULL;
05861 }
05862 #endif
05863 *handle_p = reg_item_p;
05864 return err;
05865 }
05866
05867 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05868 EXPORT_SYMBOL(rsbac_list_register);
05869 #endif
05870 int rsbac_list_register(rsbac_version_t ds_version,
05871 rsbac_list_handle_t * handle_p,
05872 struct rsbac_list_info_t *info_p,
05873 u_int flags,
05874 rsbac_list_compare_function_t * compare,
05875 rsbac_list_get_conv_t * get_conv,
05876 void *def_data, char *name, kdev_t device)
05877 {
05878 return rsbac_list_register_hashed(ds_version, handle_p, info_p, flags,
05879 compare, get_conv, def_data, name, device,
05880 1, NULL, NULL);
05881 }
05882
05883
05884
05885
05886
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901
05902
05903
05904
05905
05906
05907
05908
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928
05929 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05930 EXPORT_SYMBOL(rsbac_list_lol_register_hashed);
05931 #endif
05932 int rsbac_list_lol_register_hashed(rsbac_version_t ds_version,
05933 rsbac_list_handle_t * handle_p,
05934 struct rsbac_list_lol_info_t *info_p,
05935 u_int flags,
05936 rsbac_list_compare_function_t * compare,
05937 rsbac_list_compare_function_t * subcompare,
05938 rsbac_list_get_conv_t * get_conv,
05939 rsbac_list_get_conv_t * get_subconv,
05940 void *def_data,
05941 void *def_subdata, char *name, kdev_t device,
05942 u_int nr_hashes,
05943 rsbac_list_hash_function_t hash_function,
05944 char * old_base_name)
05945 {
05946 struct rsbac_list_lol_reg_item_t *reg_item_p;
05947 struct rsbac_list_lol_reg_item_t *new_reg_item_p;
05948 u_long lock_flags;
05949 int err = 0;
05950
05951 if (ds_version != RSBAC_LIST_VERSION)
05952 return -RSBAC_EINVALIDVERSION;
05953 if (!handle_p)
05954 return -RSBAC_EINVALIDPOINTER;
05955 *handle_p = NULL;
05956 if (!list_initialized)
05957 return -RSBAC_ENOTINITIALIZED;
05958 if (!info_p->key || !info_p->version || !info_p->desc_size)
05959 return -RSBAC_EINVALIDVALUE;
05960 if (info_p->max_age > RSBAC_LIST_MAX_AGE_LIMIT)
05961 return -RSBAC_EINVALIDVALUE;
05962 if (info_p->desc_size + info_p->data_size >
05963 RSBAC_LIST_MAX_ITEM_SIZE)
05964 return -RSBAC_EINVALIDVALUE;
05965 if (info_p->subdesc_size + info_p->subdata_size >
05966 RSBAC_LIST_MAX_ITEM_SIZE)
05967 return -RSBAC_EINVALIDVALUE;
05968 if (nr_hashes > rsbac_list_lol_max_hashes)
05969 nr_hashes = rsbac_list_lol_max_hashes;
05970 else if (nr_hashes > 2) {
05971 u_int i = 1;
05972
05973 while ((i << 1) <= nr_hashes)
05974 i = i << 1;
05975 nr_hashes = i;
05976 }
05977 if (!hash_function) {
05978 nr_hashes = 1;
05979 flags &= ~RSBAC_LIST_AUTO_HASH_RESIZE;
05980 } else
05981 if (!nr_hashes)
05982 nr_hashes = 1;
05983 if (name) {
05984 struct rsbac_list_reg_item_t *std_reg_item_p;
05985
05986 rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
05987 reg_item_p = lookup_lol_reg_name(name, device);
05988 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
05989 if (reg_item_p) {
05990 rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
05991 name, RSBAC_MAJOR(device),
05992 RSBAC_MINOR(device));
05993 return -RSBAC_EEXISTS;
05994 }
05995 rsbac_read_lock(®_head.lock, &lock_flags);
05996 std_reg_item_p = lookup_reg_name(name, device);
05997 rsbac_read_unlock(®_head.lock, &lock_flags);
05998 if (std_reg_item_p) {
05999 rsbac_pr_debug(lists, "list name %s already exists on device %02u:%02u!\n",
06000 name, RSBAC_MAJOR(device),
06001 RSBAC_MINOR(device));
06002 return -RSBAC_EEXISTS;
06003 }
06004 } else if (flags & RSBAC_LIST_PERSIST) {
06005 rsbac_printk(KERN_WARNING "rsbac_list_lol_register: trial to register persistent list of lists without name.\n");
06006 return -RSBAC_EINVALIDVALUE;
06007 }
06008
06009 if (flags & RSBAC_LIST_PERSIST) {
06010 if (RSBAC_IS_AUTO_DEV(device))
06011 device = rsbac_root_dev;
06012 if (!RSBAC_MAJOR(device))
06013 flags &= ~RSBAC_LIST_PERSIST;
06014 }
06015 rsbac_pr_debug(lists, "registering list of lists %s.\n",
06016 name);
06017 new_reg_item_p = create_lol_reg(info_p, flags, compare, subcompare,
06018 get_conv, get_subconv,
06019 def_data, def_subdata,
06020 name, device,
06021 nr_hashes, hash_function,
06022 old_base_name);
06023 if (!new_reg_item_p) {
06024 return -RSBAC_ECOULDNOTADDITEM;
06025 }
06026
06027 if (flags & RSBAC_LIST_PERSIST) {
06028 rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u.\n",
06029 name, RSBAC_MAJOR(device),
06030 RSBAC_MINOR(device));
06031 err = read_lol_list(new_reg_item_p);
06032
06033 if (err == -RSBAC_ENOTFOUND)
06034 err = 0;
06035 else if (err) {
06036 char tmp[RSBAC_MAXNAMELEN];
06037 rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u failed with error %s, unregistering list.\n",
06038 name, RSBAC_MAJOR(device),
06039 RSBAC_MINOR(device),
06040 get_error_name(tmp, err));
06041 clear_lol_reg(new_reg_item_p);
06042 return err;
06043 } else
06044 rsbac_pr_debug(lists, "restoring list %s from device %02u:%02u was successful.\n",
06045 name, RSBAC_MAJOR(device),
06046 RSBAC_MINOR(device));
06047 }
06048
06049 rsbac_write_lock(&lol_reg_head.lock, &lock_flags);
06050 reg_item_p = add_lol_reg(new_reg_item_p);
06051 rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06052 if (!reg_item_p) {
06053 rsbac_printk(KERN_WARNING "rsbac_list_lol_register: inserting list %s failed!\n",
06054 name);
06055
06056 clear_lol_reg(new_reg_item_p);
06057 return -RSBAC_ECOULDNOTADDITEM;
06058 }
06059
06060
06061 #if defined(CONFIG_RSBAC_PROC)
06062
06063 if (flags & RSBAC_LIST_BACKUP) {
06064 reg_item_p->proc_entry_p =
06065 create_proc_entry(reg_item_p->name, S_IFREG | S_IRUGO,
06066 proc_rsbac_backup_p);
06067 if (reg_item_p->proc_entry_p) {
06068 reg_item_p->proc_entry_p->read_proc =
06069 lol_backup_proc_read;
06070 reg_item_p->proc_entry_p->data = reg_item_p;
06071 }
06072 } else {
06073 reg_item_p->proc_entry_p = NULL;
06074 }
06075 #endif
06076 *handle_p = reg_item_p;
06077 return err;
06078 }
06079
06080 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06081 EXPORT_SYMBOL(rsbac_list_lol_register);
06082 #endif
06083 int rsbac_list_lol_register(rsbac_version_t ds_version,
06084 rsbac_list_handle_t * handle_p,
06085 struct rsbac_list_lol_info_t *info_p,
06086 u_int flags,
06087 rsbac_list_compare_function_t * compare,
06088 rsbac_list_compare_function_t * subcompare,
06089 rsbac_list_get_conv_t * get_conv,
06090 rsbac_list_get_conv_t * get_subconv,
06091 void *def_data,
06092 void *def_subdata, char *name, kdev_t device) {
06093 return rsbac_list_lol_register_hashed (ds_version, handle_p, info_p,
06094 flags, compare, subcompare, get_conv,
06095 get_subconv, def_data, def_subdata,
06096 name, device,
06097 1, NULL, NULL);
06098 }
06099
06100
06101
06102
06103 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06104 EXPORT_SYMBOL(rsbac_list_destroy);
06105 #endif
06106 int rsbac_list_destroy(rsbac_list_handle_t * handle_p,
06107 rsbac_list_key_t key)
06108 {
06109 struct rsbac_list_reg_item_t *reg_item_p;
06110 u_long lock_flags;
06111 int err = 0;
06112
06113 if (!handle_p)
06114 return -RSBAC_EINVALIDPOINTER;
06115 if (!*handle_p)
06116 return -RSBAC_EINVALIDLIST;
06117 if (!list_initialized)
06118 return -RSBAC_ENOTINITIALIZED;
06119
06120 rsbac_write_lock(®_head.lock, &lock_flags);
06121 reg_item_p =
06122 lookup_reg((struct rsbac_list_reg_item_t *) *handle_p);
06123 if (!reg_item_p) {
06124 rsbac_write_unlock(®_head.lock, &lock_flags);
06125 rsbac_printk(KERN_WARNING "rsbac_list_destroy: destroying list failed due to invalid handle!\n");
06126 return -RSBAC_EINVALIDLIST;
06127 }
06128 if (reg_item_p->info.key != key) {
06129 rsbac_write_unlock(®_head.lock, &lock_flags);
06130 rsbac_printk(KERN_WARNING "rsbac_list_destroy: destroying list %s denied due to invalid key!\n",
06131 reg_item_p->name);
06132 return -EPERM;
06133 }
06134 rsbac_pr_debug(lists, "destroying list %s.\n",
06135 reg_item_p->name);
06136 #if defined(CONFIG_RSBAC_PROC)
06137
06138 if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
06139 && reg_item_p->proc_entry_p) {
06140 remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06141 reg_item_p->proc_entry_p = NULL;
06142 }
06143 #endif
06144
06145 #if 0
06146 if (reg_item_p->flags & RSBAC_LIST_PERSIST)
06147 err = unlink_list(reg_item_p);
06148 #endif
06149
06150 remove_reg(reg_item_p);
06151 *handle_p = NULL;
06152 rsbac_write_unlock(®_head.lock, &lock_flags);
06153 return err;
06154 }
06155
06156 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06157 EXPORT_SYMBOL(rsbac_list_lol_destroy);
06158 #endif
06159 int rsbac_list_lol_destroy(rsbac_list_handle_t * handle_p,
06160 rsbac_list_key_t key)
06161 {
06162 struct rsbac_list_lol_reg_item_t *reg_item_p;
06163 u_long lock_flags;
06164 int err = 0;
06165
06166 if (!handle_p)
06167 return -RSBAC_EINVALIDPOINTER;
06168 if (!*handle_p)
06169 return -RSBAC_EINVALIDLIST;
06170 if (!list_initialized)
06171 return -RSBAC_ENOTINITIALIZED;
06172
06173 rsbac_write_lock(&lol_reg_head.lock, &lock_flags);
06174 reg_item_p =
06175 lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) *handle_p);
06176 if (!reg_item_p) {
06177 rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06178 rsbac_printk(KERN_WARNING "rsbac_list_lol_destroy: destroying list failed due to invalid handle!\n");
06179 return -RSBAC_EINVALIDLIST;
06180 }
06181 if (reg_item_p->info.key != key) {
06182 rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06183 rsbac_printk(KERN_WARNING "rsbac_list_lol_destroy: destroying list %s denied due to invalid key %u!\n",
06184 reg_item_p->name, key);
06185 return -EPERM;
06186 }
06187 rsbac_pr_debug(lists, "destroying list %s.\n",
06188 reg_item_p->name);
06189 #if defined(CONFIG_RSBAC_PROC)
06190
06191 if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
06192 && reg_item_p->proc_entry_p) {
06193 remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06194 reg_item_p->proc_entry_p = NULL;
06195 }
06196 #endif
06197 #if 0
06198 if (reg_item_p->flags & RSBAC_LIST_PERSIST)
06199 err = unlink_lol_list(reg_item_p);
06200 #endif
06201
06202 remove_lol_reg(reg_item_p);
06203 *handle_p = NULL;
06204 rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06205 return err;
06206 }
06207
06208
06209
06210 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06211 EXPORT_SYMBOL(rsbac_list_detach);
06212 #endif
06213 int rsbac_list_detach(rsbac_list_handle_t * handle_p, rsbac_list_key_t key)
06214 {
06215 struct rsbac_list_reg_item_t *reg_item_p;
06216 u_long lock_flags;
06217 int err = 0;
06218
06219 if (!handle_p)
06220 return -RSBAC_EINVALIDPOINTER;
06221 if (!*handle_p)
06222 return -RSBAC_EINVALIDLIST;
06223 if (!list_initialized)
06224 return -RSBAC_ENOTINITIALIZED;
06225
06226 rsbac_read_lock(®_head.lock, &lock_flags);
06227 reg_item_p =
06228 lookup_reg((struct rsbac_list_reg_item_t *) *handle_p);
06229 if (!reg_item_p) {
06230 rsbac_read_unlock(®_head.lock, &lock_flags);
06231 rsbac_printk(KERN_WARNING "rsbac_list_detach: detaching list failed due to invalid handle!\n");
06232 return -RSBAC_EINVALIDLIST;
06233 }
06234 if (reg_item_p->info.key != key) {
06235 rsbac_read_unlock(®_head.lock, &lock_flags);
06236 rsbac_printk(KERN_WARNING "rsbac_list_detach: detaching list %s denied due to invalid key %u!\n",
06237 reg_item_p->name, key);
06238 return -EPERM;
06239 }
06240 #if defined(CONFIG_RSBAC_PROC)
06241
06242 if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
06243 && reg_item_p->proc_entry_p) {
06244 remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06245 reg_item_p->proc_entry_p = NULL;
06246 }
06247 #endif
06248 #ifndef CONFIG_RSBAC_NO_WRITE
06249
06250 if ((reg_item_p->flags & RSBAC_LIST_PERSIST)
06251 && reg_item_p->dirty && !reg_item_p->no_write) {
06252 struct rsbac_list_write_head_t write_head;
06253 struct rsbac_list_write_item_t *write_item_p;
06254
06255 reg_item_p->dirty = FALSE;
06256 err = fill_buffer(reg_item_p, &write_item_p);
06257 if (!err) {
06258 write_head.head = write_item_p;
06259 write_head.tail = write_item_p;
06260 write_head.count = 1;
06261 rsbac_read_unlock(®_head.lock, &lock_flags);
06262 rsbac_list_write_buffers(write_head, TRUE);
06263 } else {
06264 rsbac_read_unlock(®_head.lock, &lock_flags);
06265 if (err != -RSBAC_ENOTWRITABLE) {
06266 rsbac_printk(KERN_WARNING "rsbac_list_detach(): fill_buffer() for list %s returned error %i\n",
06267 reg_item_p->name, err);
06268 }
06269 }
06270 } else
06271 rsbac_read_unlock(®_head.lock, &lock_flags);
06272 #else
06273 rsbac_read_unlock(®_head.lock, &lock_flags);
06274 #endif
06275
06276 *handle_p = NULL;
06277
06278 rsbac_write_lock(®_head.lock, &lock_flags);
06279 remove_reg(reg_item_p);
06280 rsbac_write_unlock(®_head.lock, &lock_flags);
06281 return err;
06282 }
06283
06284 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06285 EXPORT_SYMBOL(rsbac_list_lol_detach);
06286 #endif
06287 int rsbac_list_lol_detach(rsbac_list_handle_t * handle_p,
06288 rsbac_list_key_t key)
06289 {
06290 struct rsbac_list_lol_reg_item_t *reg_item_p;
06291 u_long lock_flags;
06292 int err = 0;
06293
06294 if (!handle_p)
06295 return -RSBAC_EINVALIDPOINTER;
06296 if (!*handle_p)
06297 return -RSBAC_EINVALIDLIST;
06298 if (!list_initialized)
06299 return -RSBAC_ENOTINITIALIZED;
06300
06301 rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
06302 reg_item_p =
06303 lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) *handle_p);
06304 if (!reg_item_p) {
06305 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06306 rsbac_printk(KERN_WARNING "rsbac_list_lol_detach: detaching list failed due to invalid handle!\n");
06307 return -RSBAC_EINVALIDLIST;
06308 }
06309 if (reg_item_p->info.key != key) {
06310 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06311 rsbac_printk(KERN_WARNING "rsbac_list_lol_detach: detaching list %s denied due to invalid key %u!\n",
06312 reg_item_p->name, key);
06313 return -EPERM;
06314 }
06315 #if defined(CONFIG_RSBAC_PROC)
06316
06317 if ((reg_item_p->flags & RSBAC_LIST_BACKUP)
06318 && reg_item_p->proc_entry_p) {
06319 remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06320 reg_item_p->proc_entry_p = NULL;
06321 }
06322 #endif
06323 #ifndef CONFIG_RSBAC_NO_WRITE
06324
06325 if ((reg_item_p->flags & RSBAC_LIST_PERSIST)
06326 && reg_item_p->dirty && !reg_item_p->no_write) {
06327 struct rsbac_list_lol_write_head_t write_head;
06328 struct rsbac_list_lol_write_item_t *write_item_p;
06329
06330 reg_item_p->dirty = FALSE;
06331 err = fill_lol_buffer(reg_item_p, &write_item_p);
06332 if (!err) {
06333 write_head.head = write_item_p;
06334 write_head.tail = write_item_p;
06335 write_head.count = 1;
06336 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06337 rsbac_list_write_lol_buffers(write_head, TRUE);
06338 } else {
06339 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06340 if (err != -RSBAC_ENOTWRITABLE) {
06341 rsbac_printk(KERN_WARNING "rsbac_list_lol_detach(): fill_buffer() for list %s returned error %i\n",
06342 reg_item_p->name, err);
06343 }
06344 }
06345 } else
06346 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06347 #else
06348 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06349 #endif
06350
06351 *handle_p = NULL;
06352
06353 rsbac_write_lock(&lol_reg_head.lock, &lock_flags);
06354 remove_lol_reg(reg_item_p);
06355 rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06356 return err;
06357 }
06358
06359
06360
06361 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06362 EXPORT_SYMBOL(rsbac_list_no_write);
06363 #endif
06364 int rsbac_list_no_write(rsbac_list_handle_t handle, rsbac_list_key_t key,
06365 rsbac_boolean_t no_write)
06366 {
06367 struct rsbac_list_reg_item_t *reg_item_p;
06368 u_long lock_flags;
06369
06370 if (!handle)
06371 return -RSBAC_EINVALIDLIST;
06372 if ((no_write != FALSE) && (no_write != TRUE))
06373 return -RSBAC_EINVALIDVALUE;
06374 if (!list_initialized)
06375 return -RSBAC_ENOTINITIALIZED;
06376
06377 rsbac_read_lock(®_head.lock, &lock_flags);
06378 reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) handle);
06379 if (!reg_item_p) {
06380 rsbac_read_unlock(®_head.lock, &lock_flags);
06381 rsbac_printk(KERN_WARNING "rsbac_list_no_write: setting no_write for list denied due to invalid handle!\n");
06382 return -RSBAC_EINVALIDLIST;
06383 }
06384 if (reg_item_p->info.key != key) {
06385 rsbac_read_unlock(®_head.lock, &lock_flags);
06386 rsbac_printk(KERN_WARNING "rsbac_list_no_write: setting no_write for list %s denied due to invalid key %u!\n",
06387 reg_item_p->name, key);
06388 return -EPERM;
06389 }
06390 reg_item_p->no_write = no_write;
06391 rsbac_read_unlock(®_head.lock, &lock_flags);
06392 return 0;
06393 }
06394
06395 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06396 EXPORT_SYMBOL(rsbac_list_lol_no_write);
06397 #endif
06398 int rsbac_list_lol_no_write(rsbac_list_handle_t handle,
06399 rsbac_list_key_t key, rsbac_boolean_t no_write)
06400 {
06401 struct rsbac_list_lol_reg_item_t *reg_item_p;
06402 u_long lock_flags;
06403
06404 if (!handle)
06405 return -RSBAC_EINVALIDLIST;
06406 if ((no_write != FALSE) && (no_write != TRUE))
06407 return -RSBAC_EINVALIDVALUE;
06408 if (!list_initialized)
06409 return -RSBAC_ENOTINITIALIZED;
06410
06411 rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
06412 reg_item_p =
06413 lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) handle);
06414 if (!reg_item_p) {
06415 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06416 rsbac_printk(KERN_WARNING "rsbac_list_lol_no_write: setting no_write for list denied due to invalid handle!\n");
06417 return -RSBAC_EINVALIDLIST;
06418 }
06419 if (reg_item_p->info.key != key) {
06420 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06421 rsbac_printk(KERN_WARNING "rsbac_list_lol_no_write: setting no_write for list %s denied due to invalid key %u!\n",
06422 reg_item_p->name, key);
06423 return -EPERM;
06424 }
06425 reg_item_p->no_write = no_write;
06426 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06427 return 0;
06428 }
06429
06430
06431 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06432 EXPORT_SYMBOL(rsbac_list_max_items);
06433 #endif
06434 int rsbac_list_max_items(rsbac_list_handle_t handle, rsbac_list_key_t key,
06435 u_int max_items)
06436 {
06437 struct rsbac_list_reg_item_t *reg_item_p;
06438 u_long lock_flags;
06439
06440 if (!handle)
06441 return -RSBAC_EINVALIDLIST;
06442 if (!list_initialized)
06443 return -RSBAC_ENOTINITIALIZED;
06444
06445 rsbac_read_lock(®_head.lock, &lock_flags);
06446 reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) handle);
06447 if (!reg_item_p) {
06448 rsbac_read_unlock(®_head.lock, &lock_flags);
06449 rsbac_printk(KERN_WARNING "rsbac_list_max_items: setting max_items_per_hash for list denied due to invalid handle!\n");
06450 return -RSBAC_EINVALIDLIST;
06451 }
06452 if (reg_item_p->info.key != key) {
06453 rsbac_read_unlock(®_head.lock, &lock_flags);
06454 rsbac_printk(KERN_WARNING "rsbac_list_max_items: setting max_items_per_hash for list %s denied due to invalid key %u!\n",
06455 reg_item_p->name, key);
06456 return -EPERM;
06457 }
06458 reg_item_p->max_items_per_hash = rsbac_min(max_items, RSBAC_LIST_MAX_NR_ITEMS_LIMIT);
06459 rsbac_read_unlock(®_head.lock, &lock_flags);
06460 return 0;
06461 }
06462
06463
06464 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06465 EXPORT_SYMBOL(rsbac_list_lol_max_items);
06466 #endif
06467 int rsbac_list_lol_max_items(rsbac_list_handle_t handle, rsbac_list_key_t key,
06468 u_int max_items, u_int max_subitems)
06469 {
06470 struct rsbac_list_lol_reg_item_t *reg_item_p;
06471 u_long lock_flags;
06472
06473 if (!handle)
06474 return -RSBAC_EINVALIDLIST;
06475 if (!list_initialized)
06476 return -RSBAC_ENOTINITIALIZED;
06477
06478 rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
06479 reg_item_p = lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) handle);
06480 if (!reg_item_p) {
06481 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06482 rsbac_printk(KERN_WARNING "rsbac_list_lol_max_items: setting max_items_per_hash for list denied due to invalid handle!\n");
06483 return -RSBAC_EINVALIDLIST;
06484 }
06485 if (reg_item_p->info.key != key) {
06486 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06487 rsbac_printk(KERN_WARNING "rsbac_list_lol_max_items: setting max_items_per_hash for list %s denied due to invalid key %u!\n",
06488 reg_item_p->name, key);
06489 return -EPERM;
06490 }
06491 reg_item_p->max_items_per_hash = rsbac_min(max_items, RSBAC_LIST_MAX_NR_ITEMS_LIMIT);
06492 reg_item_p->max_subitems = rsbac_min(max_subitems, RSBAC_LIST_MAX_NR_ITEMS_LIMIT);
06493 rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06494 return 0;
06495 }
06496
06497
06498
06499
06500
06501
06502 #ifdef CONFIG_RSBAC_LIST_TRANS
06503 static int do_commit(rsbac_list_ta_number_t ta_number)
06504 {
06505
06506
06507
06508
06509
06510
06511
06512
06513
06514
06515 struct rsbac_list_reg_item_t *list;
06516 struct rsbac_list_lol_reg_item_t *lol_list;
06517 u_long lock_flags;
06518 u_long lol_lock_flags;
06519 int i;
06520
06521 rsbac_write_lock(®_head.lock, &lock_flags);
06522 rsbac_write_lock(&lol_reg_head.lock, &lol_lock_flags);
06523 list = reg_head.head;
06524 while (list) {
06525 for (i=0; i<list->nr_hashes; i++) {
06526 if (list->hashed[i].ta_copied == ta_number) {
06527 remove_all_items(list, i);
06528 list->hashed[i].head = list->hashed[i].ta_head;
06529 list->hashed[i].tail = list->hashed[i].ta_tail;
06530 list->hashed[i].curr = list->hashed[i].ta_curr;
06531 list->hashed[i].count = list->hashed[i].ta_count;
06532 list->hashed[i].ta_head = NULL;
06533 list->hashed[i].ta_tail = NULL;
06534 list->hashed[i].ta_curr = NULL;
06535 list->hashed[i].ta_count = 0;
06536 list->hashed[i].ta_copied = 0;
06537 list->dirty = TRUE;
06538 }
06539 }
06540 list = list->next;
06541 }
06542 lol_list = lol_reg_head.head;
06543 while (lol_list) {
06544 for (i=0; i<lol_list->nr_hashes; i++) {
06545 if (lol_list->hashed[i].ta_copied == ta_number) {
06546 remove_all_lol_items(lol_list, i);
06547 lol_list->hashed[i].head = lol_list->hashed[i].ta_head;
06548 lol_list->hashed[i].tail = lol_list->hashed[i].ta_tail;
06549 lol_list->hashed[i].curr = lol_list->hashed[i].ta_curr;
06550 lol_list->hashed[i].count = lol_list->hashed[i].ta_count;
06551 lol_list->hashed[i].ta_head = NULL;
06552 lol_list->hashed[i].ta_tail = NULL;
06553 lol_list->hashed[i].ta_curr = NULL;
06554 lol_list->hashed[i].ta_count = 0;
06555 lol_list->hashed[i].ta_copied = 0;
06556 lol_list->dirty = TRUE;
06557 }
06558 }
06559 lol_list = lol_list->next;
06560 }
06561 rsbac_write_unlock(&lol_reg_head.lock, &lol_lock_flags);
06562 rsbac_write_unlock(®_head.lock, &lock_flags);
06563
06564 return 0;
06565 }
06566
06567 int rsbac_list_ta_commit(rsbac_list_ta_number_t ta_number, char *password)
06568 {
06569 int err;
06570 struct rsbac_list_ta_data_t ta_data;
06571
06572 err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
06573 if (err)
06574 return err;
06575 if ((ta_data.commit_uid != RSBAC_ALL_USERS)
06576 && (ta_data.commit_uid != current->uid)
06577 )
06578 return -EPERM;
06579
06580 if (ta_data.password[0]) {
06581 if (!password)
06582 return -EPERM;
06583 if (strncmp
06584 (ta_data.password, password,
06585 RSBAC_LIST_TA_MAX_PASSLEN))
06586 return -EPERM;
06587 }
06588 spin_lock(&ta_lock);
06589 if (ta_committing || ta_forgetting) {
06590 spin_unlock(&ta_lock);
06591 return -RSBAC_EBUSY;
06592 }
06593 ta_committing = TRUE;
06594 spin_unlock(&ta_lock);
06595
06596 rsbac_printk(KERN_INFO "rsbac_list_ta_commit(): committing transaction %u\n",
06597 ta_number);
06598
06599 err = do_commit(ta_number);
06600 if (!err)
06601 rsbac_list_remove(ta_handle, &ta_number);
06602 ta_committing = FALSE;
06603 return err;
06604 }
06605
06606 static int do_forget(rsbac_list_ta_number_t ta_number)
06607 {
06608 struct rsbac_list_reg_item_t *list;
06609 struct rsbac_list_lol_reg_item_t *lol_list;
06610 u_long lock_flags;
06611 u_long lol_lock_flags;
06612 int i;
06613
06614 spin_lock(&ta_lock);
06615 if (ta_committing || ta_forgetting) {
06616 spin_unlock(&ta_lock);
06617 return -RSBAC_EBUSY;
06618 }
06619 ta_forgetting = TRUE;
06620 spin_unlock(&ta_lock);
06621
06622 rsbac_printk(KERN_INFO "rsbac_list_ta_forget(): removing transaction %u\n",
06623 ta_number);
06624
06625
06626
06627
06628
06629
06630
06631
06632
06633 rsbac_write_lock(®_head.lock, &lock_flags);
06634 rsbac_write_lock(&lol_reg_head.lock, &lol_lock_flags);
06635 list = reg_head.head;
06636 while (list) {
06637 for (i=0; i<list->nr_hashes; i++) {
06638 if (list->hashed[i].ta_copied == ta_number) {
06639 ta_remove_all_items(list, i);
06640 list->hashed[i].ta_copied = 0;
06641 }
06642 }
06643 list = list->next;
06644 }
06645 lol_list = lol_reg_head.head;
06646 while (lol_list) {
06647 for (i=0; i<lol_list->nr_hashes; i++) {
06648 if (lol_list->hashed[i].ta_copied == ta_number) {
06649 ta_remove_all_lol_items(lol_list, i);
06650 lol_list->hashed[i].ta_copied = 0;
06651 }
06652 }
06653 lol_list = lol_list->next;
06654 }
06655 rsbac_write_unlock(&lol_reg_head.lock, &lol_lock_flags);
06656 rsbac_write_unlock(®_head.lock, &lock_flags);
06657
06658 rsbac_list_remove(ta_handle, &ta_number);
06659 ta_forgetting = FALSE;
06660
06661 return 0;
06662 }
06663
06664 int rsbac_list_ta_forget(rsbac_list_ta_number_t ta_number, char *password)
06665 {
06666 int err;
06667 struct rsbac_list_ta_data_t ta_data;
06668
06669 err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
06670 if (err)
06671 return err;
06672 if ((ta_data.commit_uid != RSBAC_ALL_USERS)
06673 && (ta_data.commit_uid != current->uid)
06674 )
06675 return -EPERM;
06676 if (ta_data.password[0]) {
06677 if (!password)
06678 return -EPERM;
06679 if (strncmp
06680 (ta_data.password, password,
06681 RSBAC_LIST_TA_MAX_PASSLEN))
06682 return -EPERM;
06683 }
06684 return do_forget(ta_number);
06685 }
06686
06687 int rsbac_list_ta_begin(rsbac_time_t ttl,
06688 rsbac_list_ta_number_t * ta_number_p,
06689 rsbac_uid_t commit_uid, char *password)
06690 {
06691 int err;
06692 rsbac_list_ta_number_t ta;
06693 struct rsbac_list_ta_data_t ta_data;
06694
06695 #ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
06696 get_random_bytes(&ta, sizeof(ta));
06697 #else
06698 ta = ta_next++;
06699 #endif
06700 while (rsbac_list_exist(ta_handle, &ta)) {
06701 #ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
06702 get_random_bytes(&ta, sizeof(ta));
06703 #else
06704 ta = ta_next++;
06705 #endif
06706 }
06707 if (!ttl || (ttl > CONFIG_RSBAC_LIST_TRANS_MAX_TTL))
06708 ttl = CONFIG_RSBAC_LIST_TRANS_MAX_TTL;
06709
06710 rsbac_printk(KERN_INFO "rsbac_list_ta_begin(): starting transaction %u with ttl of %us\n",
06711 ta, ttl);
06712
06713 ta_data.start = RSBAC_CURRENT_TIME;
06714 ta_data.timeout = ta_data.start + ttl;
06715 ta_data.commit_uid = commit_uid;
06716 if (password) {
06717 strncpy(ta_data.password, password,
06718 RSBAC_LIST_TA_MAX_PASSLEN - 1);
06719 ta_data.password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
06720 } else
06721 ta_data.password[0] = 0;
06722 err = rsbac_list_add(ta_handle, &ta, &ta_data);
06723 if (!err)
06724 *ta_number_p = ta;
06725 return err;
06726 }
06727
06728 int rsbac_list_ta_refresh(rsbac_time_t ttl,
06729 rsbac_list_ta_number_t ta_number, char *password)
06730 {
06731 struct rsbac_list_ta_data_t ta_data;
06732 int err;
06733
06734 if (!rsbac_list_exist(ta_handle, &ta_number)) {
06735 return -RSBAC_ENOTFOUND;
06736 }
06737 if (!ttl || (ttl > CONFIG_RSBAC_LIST_TRANS_MAX_TTL))
06738 ttl = CONFIG_RSBAC_LIST_TRANS_MAX_TTL;
06739
06740 rsbac_printk(KERN_INFO "rsbac_list_ta_refresh(): refreshing transaction %u for %us\n",
06741 ta_number, ttl);
06742
06743 err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
06744 if (err)
06745 return err;
06746 if ((ta_data.commit_uid != RSBAC_ALL_USERS)
06747 && (ta_data.commit_uid != current->uid)
06748 )
06749 return -EPERM;
06750 if (ta_data.password[0]) {
06751 if (!password)
06752 return -EPERM;
06753 if (strncmp
06754 (ta_data.password, password,
06755 RSBAC_LIST_TA_MAX_PASSLEN))
06756 return -EPERM;
06757 }
06758 ta_data.timeout = RSBAC_CURRENT_TIME + ttl;
06759 return rsbac_list_add(ta_handle, &ta_number, &ta_data);
06760 }
06761 #endif
06762
06763
06764
06765
06766
06767
06768
06769
06770 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06771 EXPORT_SYMBOL(rsbac_ta_list_add_ttl);
06772 #endif
06773 int rsbac_ta_list_add_ttl(rsbac_list_ta_number_t ta_number,
06774 rsbac_list_handle_t handle,
06775 rsbac_time_t ttl, void *desc, void *data)
06776 {
06777 struct rsbac_list_reg_item_t *list;
06778 struct rsbac_list_item_t *item_p;
06779 u_long lock_flags, rlock_flags;
06780 u_int hash = 0;
06781
06782 if (!handle)
06783 return -RSBAC_EINVALIDLIST;
06784 if (!desc)
06785 return -RSBAC_EINVALIDVALUE;
06786 if (!list_initialized)
06787 return -RSBAC_ENOTINITIALIZED;
06788
06789 list = (struct rsbac_list_reg_item_t *) handle;
06790 if (!list || (list->self != list))
06791 return -RSBAC_EINVALIDLIST;
06792
06793 #ifdef CONFIG_RSBAC_LIST_TRANS
06794 if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
06795 return -RSBAC_EINVALIDTRANSACTION;
06796 #endif
06797
06798 rsbac_read_lock(®_head.lock, &rlock_flags);
06799 if (list->info.data_size && !data) {
06800 rsbac_read_unlock(®_head.lock, &rlock_flags);
06801 return -RSBAC_EINVALIDVALUE;
06802 }
06803
06804
06805
06806
06807 if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
06808 if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
06809 ttl = RSBAC_LIST_MAX_AGE_LIMIT;
06810 ttl += RSBAC_CURRENT_TIME;
06811 }
06812 rsbac_write_lock(&list->lock, &lock_flags);
06813
06814 if(list->hash_function)
06815 hash = list->hash_function(desc, list->nr_hashes);
06816 #ifdef CONFIG_RSBAC_LIST_TRANS
06817 if (!ta_number)
06818 #endif
06819 {
06820 item_p = lookup_item(list, desc);
06821 if (item_p) {
06822 if (ttl != RSBAC_LIST_TTL_KEEP)
06823 item_p->max_age = ttl;
06824 if (data && list->info.data_size) {
06825 if (list->def_data
06826 && !item_p->max_age
06827 && !memcmp(list->def_data, data,
06828 list->info.data_size)
06829 )
06830 do_remove_item(list, item_p, hash);
06831 else
06832 memcpy(((char *) item_p) +
06833 sizeof(*item_p) +
06834 list->info.desc_size, data,
06835 list->info.data_size);
06836 }
06837 } else {
06838 if (ttl == RSBAC_LIST_TTL_KEEP)
06839 ttl = 0;
06840 if (!list->def_data
06841 || memcmp(list->def_data, data,
06842 list->info.data_size)
06843 )
06844 add_item(list, ttl, desc, data);
06845 }
06846 touch(list);
06847 list->dirty = TRUE;
06848 }
06849 #ifdef CONFIG_RSBAC_LIST_TRANS
06850 if (list->hashed[hash].ta_copied || ta_number) {
06851 if (!list->hashed[hash].ta_copied)
06852 ta_copy(ta_number, list, hash);
06853 else if (ta_number) {
06854 if (list->hashed[hash].ta_copied != ta_number) {
06855 rsbac_write_unlock(&list->lock,
06856 &lock_flags);
06857 rsbac_read_unlock(®_head.lock,
06858 &rlock_flags);
06859 return -RSBAC_EBUSY;
06860 }
06861 } else
06862 ta_number = list->hashed[hash].ta_copied;
06863 item_p = ta_lookup_item(ta_number, list, desc);
06864 if (item_p) {
06865 if (ttl != RSBAC_LIST_TTL_KEEP)
06866 item_p->max_age = ttl;
06867 if (data && list->info.data_size) {
06868 if (list->def_data
06869 && !item_p->max_age
06870 && !memcmp(list->def_data, data,
06871 list->info.data_size)
06872 )
06873 ta_do_remove_item(list, item_p, hash);
06874 else
06875 memcpy(((char *) item_p) +
06876 sizeof(*item_p) +
06877 list->info.desc_size, data,
06878 list->info.data_size);
06879 }
06880 } else {
06881 if (ttl == RSBAC_LIST_TTL_KEEP)
06882 ttl = 0;
06883 if (!list->def_data
06884 || memcmp(list->def_data, data,
06885 list->info.data_size)
06886 )
06887 ta_add_item(ta_number, list, ttl, desc,
06888 data);
06889 }
06890 }
06891 #endif
06892 rsbac_write_unlock(&list->lock, &lock_flags);
06893 rsbac_read_unlock(®_head.lock, &rlock_flags);
06894 return 0;
06895 }
06896
06897
06898
06899 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06900 EXPORT_SYMBOL(rsbac_ta_list_lol_subadd_ttl);
06901 #endif
06902 int rsbac_ta_list_lol_subadd_ttl(rsbac_list_ta_number_t ta_number,
06903 rsbac_list_handle_t handle,
06904 rsbac_time_t ttl,
06905 void *desc, void *subdesc, void *subdata)
06906 {
06907 struct rsbac_list_lol_reg_item_t *list;
06908 struct rsbac_list_lol_item_t *sublist;
06909 struct rsbac_list_item_t *item_p;
06910 u_long lock_flags, rlock_flags;
06911 int err = 0;
06912 u_int hash = 0;
06913
06914 if (!handle)
06915 return -RSBAC_EINVALIDLIST;
06916 if (!desc || !subdesc)
06917 return -RSBAC_EINVALIDVALUE;
06918 if (!list_initialized)
06919 return -RSBAC_ENOTINITIALIZED;
06920
06921 list = (struct rsbac_list_lol_reg_item_t *) handle;
06922 if (!list || (list->self != list))
06923 return -RSBAC_EINVALIDLIST;
06924
06925 #ifdef CONFIG_RSBAC_LIST_TRANS
06926 if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
06927 return -RSBAC_EINVALIDTRANSACTION;
06928 #endif
06929
06930 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
06931 if (list->info.subdata_size && !subdata) {
06932 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
06933 return -RSBAC_EINVALIDVALUE;
06934 }
06935
06936
06937
06938
06939 rsbac_write_lock(&list->lock, &lock_flags);
06940
06941 if(list->hash_function)
06942 hash = list->hash_function(desc, list->nr_hashes);
06943 #ifdef CONFIG_RSBAC_LIST_TRANS
06944 if (!ta_number)
06945 #endif
06946 {
06947 sublist = lookup_lol_item(list, desc);
06948 if (!sublist && (list->flags & RSBAC_LIST_DEF_DATA)
06949 )
06950 sublist =
06951 add_lol_item(list, 0, desc, list->def_data);
06952 if (sublist) {
06953 if (sublist->max_age
06954 && (sublist->max_age <= RSBAC_CURRENT_TIME)
06955 ) {
06956 remove_lol_item(list, desc);
06957 err = -RSBAC_EINVALIDTARGET;
06958 } else {
06959
06960 if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
06961 if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
06962 ttl =
06963 RSBAC_LIST_MAX_AGE_LIMIT;
06964 ttl += RSBAC_CURRENT_TIME;
06965 }
06966 item_p =
06967 lookup_lol_subitem(list, sublist,
06968 subdesc);
06969 if (item_p) {
06970 if (ttl != RSBAC_LIST_TTL_KEEP)
06971 item_p->max_age = ttl;
06972 if (subdata
06973 && list->info.subdata_size) {
06974 if (list->def_subdata
06975 && !item_p->max_age
06976 && !memcmp(list->
06977 def_subdata,
06978 subdata,
06979 list->info.
06980 subdata_size)
06981 )
06982 do_remove_lol_subitem
06983 (sublist,
06984 item_p);
06985 else
06986 memcpy(((char *)
06987 item_p) +
06988 sizeof
06989 (*item_p) +
06990 list->info.
06991 subdesc_size,
06992 subdata,
06993 list->info.
06994 subdata_size);
06995 }
06996 } else {
06997 if (ttl == RSBAC_LIST_TTL_KEEP)
06998 ttl = 0;
06999 if (!list->def_subdata
07000 || memcmp(list->def_subdata,
07001 subdata,
07002 list->info.
07003 subdata_size)
07004 )
07005 add_lol_subitem(list,
07006 sublist,
07007 ttl,
07008 subdesc,
07009 subdata);
07010 }
07011 lol_touch(list);
07012 list->dirty = TRUE;
07013 }
07014 } else {
07015 err = -RSBAC_EINVALIDTARGET;
07016 goto out_unlock;
07017 }
07018 }
07019 #ifdef CONFIG_RSBAC_LIST_TRANS
07020 if (list->hashed[hash].ta_copied || ta_number) {
07021 if (!list->hashed[hash].ta_copied) {
07022 if ((err = ta_lol_copy(ta_number, list, hash)))
07023 goto out_unlock;
07024 } else if (ta_number) {
07025 if (list->hashed[hash].ta_copied != ta_number) {
07026 err = -RSBAC_EBUSY;
07027 goto out_unlock;
07028 }
07029 } else
07030 ta_number = list->hashed[hash].ta_copied;
07031 sublist = ta_lookup_lol_item(ta_number, list, desc);
07032 if (!sublist && (list->flags & RSBAC_LIST_DEF_DATA)
07033 )
07034 sublist =
07035 ta_add_lol_item(ta_number, list, 0, desc,
07036 list->def_data);
07037 if (sublist) {
07038 if (sublist->max_age
07039 && (sublist->max_age <= RSBAC_CURRENT_TIME)
07040 ) {
07041 ta_remove_lol_item(ta_number, list, desc);
07042 err = -RSBAC_EINVALIDTARGET;
07043 } else {
07044
07045 if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
07046 if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
07047 ttl =
07048 RSBAC_LIST_MAX_AGE_LIMIT;
07049 ttl += RSBAC_CURRENT_TIME;
07050 }
07051 item_p =
07052 lookup_lol_subitem(list, sublist,
07053 subdesc);
07054 if (item_p) {
07055 if (ttl != RSBAC_LIST_TTL_KEEP)
07056 item_p->max_age = ttl;
07057 if (subdata
07058 && list->info.subdata_size) {
07059 if (list->def_subdata
07060 && !item_p->max_age
07061 && !memcmp(list->
07062 def_subdata,
07063 subdata,
07064 list->info.
07065 subdata_size)
07066 )
07067 do_remove_lol_subitem
07068 (sublist,
07069 item_p);
07070 else
07071 memcpy(((char *)
07072 item_p) +
07073 sizeof
07074 (*item_p) +
07075 list->info.
07076 subdesc_size,
07077 subdata,
07078 list->info.
07079 subdata_size);
07080 }
07081 } else {
07082 if (ttl == RSBAC_LIST_TTL_KEEP)
07083 ttl = 0;
07084 if (!list->def_subdata
07085 || memcmp(list->def_subdata,
07086 subdata,
07087 list->info.
07088 subdata_size)
07089 )
07090 add_lol_subitem(list,
07091 sublist,
07092 ttl,
07093 subdesc,
07094 subdata);
07095 }
07096 }
07097 } else {
07098 err = -RSBAC_EINVALIDTARGET;
07099 }
07100 }
07101 #endif
07102
07103 out_unlock:
07104 rsbac_write_unlock(&list->lock, &lock_flags);
07105 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07106 return err;
07107 }
07108
07109
07110
07111 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07112 EXPORT_SYMBOL(rsbac_ta_list_lol_add_ttl);
07113 #endif
07114 int rsbac_ta_list_lol_add_ttl(rsbac_list_ta_number_t ta_number,
07115 rsbac_list_handle_t handle,
07116 rsbac_time_t ttl, void *desc, void *data)
07117 {
07118 struct rsbac_list_lol_reg_item_t *list;
07119 struct rsbac_list_lol_item_t *item_p;
07120 u_long lock_flags, rlock_flags;
07121 u_int hash = 0;
07122
07123 if (!handle)
07124 return -RSBAC_EINVALIDLIST;
07125 if (!desc)
07126 return -RSBAC_EINVALIDVALUE;
07127 if (!list_initialized)
07128 return -RSBAC_ENOTINITIALIZED;
07129
07130 list = (struct rsbac_list_lol_reg_item_t *) handle;
07131 if (!list || (list->self != list))
07132 return -RSBAC_EINVALIDLIST;
07133
07134 #ifdef CONFIG_RSBAC_LIST_TRANS
07135 if (ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
07136 return -RSBAC_EINVALIDTRANSACTION;
07137 #endif
07138
07139 if (ttl && (ttl != RSBAC_LIST_TTL_KEEP)) {
07140 if (ttl > RSBAC_LIST_MAX_AGE_LIMIT)
07141 ttl = RSBAC_LIST_MAX_AGE_LIMIT;
07142 ttl += RSBAC_CURRENT_TIME;
07143 }
07144
07145 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07146 if (list->info.data_size && !data) {
07147 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07148 return -RSBAC_EINVALIDVALUE;
07149 }
07150
07151
07152
07153
07154 rsbac_write_lock(&list->lock, &lock_flags);
07155
07156 if(list->hash_function)
07157 hash = list->hash_function(desc, list->nr_hashes);
07158 #ifdef CONFIG_RSBAC_LIST_TRANS
07159 if (!ta_number)
07160 #endif
07161 {
07162 item_p = lookup_lol_item(list, desc);
07163 if (item_p) {
07164 if (ttl != RSBAC_LIST_TTL_KEEP)
07165 item_p->max_age = ttl;
07166 if (data && list->info.data_size) {
07167 if (list->def_data
07168 && !item_p->max_age
07169 && !memcmp(list->def_data, data,
07170 list->info.data_size)
07171 && !item_p->count)
07172 do_remove_lol_item(list, item_p, hash);
07173 else
07174 memcpy(((char *) item_p) +
07175 sizeof(*item_p) +
07176 list->info.desc_size, data,
07177 list->info.data_size);
07178 }
07179 } else {
07180 if (ttl == RSBAC_LIST_TTL_KEEP)
07181 ttl = 0;
07182 if (!list->def_data
07183 || memcmp(list->def_data, data,
07184 list->info.data_size)
07185 )
07186 add_lol_item(list, ttl, desc, data);
07187 }
07188 lol_touch(list);
07189 list->dirty = TRUE;
07190 }
07191 #ifdef CONFIG_RSBAC_LIST_TRANS
07192 if (list->hashed[hash].ta_copied || ta_number) {
07193 if (!list->hashed[hash].ta_copied)
07194 ta_lol_copy(ta_number, list, hash);
07195 else if (ta_number) {
07196 if (list->hashed[hash].ta_copied != ta_number) {
07197 rsbac_write_unlock(&list->lock,
07198 &lock_flags);
07199 rsbac_read_unlock(&lol_reg_head.lock,
07200 &rlock_flags);
07201 return -RSBAC_EBUSY;
07202 }
07203 } else
07204 ta_number = list->hashed[hash].ta_copied;
07205 item_p = ta_lookup_lol_item(ta_number, list, desc);
07206 if (item_p) {
07207 if (ttl != RSBAC_LIST_TTL_KEEP)
07208 item_p->max_age = ttl;
07209 if (data && list->info.data_size) {
07210 if (list->def_data
07211 && !item_p->max_age
07212 && !memcmp(list->def_data, data,
07213 list->info.data_size)
07214 && !item_p->count)
07215 ta_do_remove_lol_item(list,
07216 item_p,
07217 hash);
07218 else
07219 memcpy(((char *) item_p) +
07220 sizeof(*item_p) +
07221 list->info.desc_size, data,
07222 list->info.data_size);
07223 }
07224 } else {
07225 if (ttl == RSBAC_LIST_TTL_KEEP)
07226 ttl = 0;
07227 if (!list->def_data
07228 || memcmp(list->def_data, data,
07229 list->info.data_size)
07230 )
07231 ta_add_lol_item(ta_number, list, ttl, desc,
07232 data);
07233 }
07234 }
07235 #endif
07236 rsbac_write_unlock(&list->lock, &lock_flags);
07237 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07238 return 0;
07239 }
07240
07241
07242 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07243 EXPORT_SYMBOL(rsbac_ta_list_remove);
07244 #endif
07245 int rsbac_ta_list_remove(rsbac_list_ta_number_t ta_number,
07246 rsbac_list_handle_t handle, void *desc)
07247 {
07248 struct rsbac_list_reg_item_t *list;
07249 u_long lock_flags, rlock_flags;
07250 u_int hash = 0;
07251
07252 if (!handle)
07253 return -RSBAC_EINVALIDLIST;
07254 if (!desc)
07255 return -RSBAC_EINVALIDVALUE;
07256 if (!list_initialized)
07257 return -RSBAC_ENOTINITIALIZED;
07258
07259 list = (struct rsbac_list_reg_item_t *) handle;
07260 if (!list || (list->self != list))
07261 return -RSBAC_EINVALIDLIST;
07262
07263 #ifdef CONFIG_RSBAC_LIST_TRANS
07264 if (ta_number) {
07265 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07266 return -RSBAC_EINVALIDTRANSACTION;
07267 }
07268 #endif
07269
07270 rsbac_read_lock(®_head.lock, &rlock_flags);
07271
07272
07273
07274 if(list->hash_function)
07275 hash = list->hash_function(desc, list->nr_hashes);
07276 rsbac_write_lock(&list->lock, &lock_flags);
07277 #ifdef CONFIG_RSBAC_LIST_TRANS
07278 if (list->hashed[hash].ta_copied) {
07279 if (ta_number) {
07280 if (ta_lookup_item(list->hashed[hash].ta_copied, list, desc)) {
07281 if (list->hashed[hash].ta_copied != ta_number) {
07282 rsbac_write_unlock(&list->lock,
07283 &lock_flags);
07284 rsbac_read_unlock(®_head.lock,
07285 &rlock_flags);
07286 return -RSBAC_EBUSY;
07287 } else
07288 ta_remove_item(ta_number, list,
07289 desc);
07290 }
07291 } else
07292 ta_remove_item(list->hashed[hash].ta_copied, list, desc);
07293 } else {
07294 if (ta_number && lookup_item(list, desc)) {
07295 ta_copy(ta_number, list, hash);
07296 ta_remove_item(ta_number, list, desc);
07297 }
07298 }
07299 if (!ta_number)
07300 #endif
07301 {
07302 if (lookup_item(list, desc)) {
07303 remove_item(list, desc);
07304 touch(list);
07305 list->dirty = TRUE;
07306 }
07307 }
07308 rsbac_write_unlock(&list->lock, &lock_flags);
07309 rsbac_read_unlock(®_head.lock, &rlock_flags);
07310 return 0;
07311 }
07312
07313
07314 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07315 EXPORT_SYMBOL(rsbac_ta_list_remove_all);
07316 #endif
07317 int rsbac_ta_list_remove_all(rsbac_list_ta_number_t ta_number,
07318 rsbac_list_handle_t handle)
07319 {
07320 struct rsbac_list_reg_item_t *list;
07321 u_long lock_flags, rlock_flags;
07322 int i;
07323
07324 if (!handle)
07325 return -RSBAC_EINVALIDLIST;
07326 if (!list_initialized)
07327 return -RSBAC_ENOTINITIALIZED;
07328
07329 list = (struct rsbac_list_reg_item_t *) handle;
07330 if (list->self != list)
07331 return -RSBAC_EINVALIDLIST;
07332
07333 #ifdef CONFIG_RSBAC_LIST_TRANS
07334 if (ta_number) {
07335 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07336 return -RSBAC_EINVALIDTRANSACTION;
07337 }
07338 #endif
07339
07340 rsbac_read_lock(®_head.lock, &rlock_flags);
07341
07342
07343
07344 rsbac_write_lock(&list->lock, &lock_flags);
07345 #ifdef CONFIG_RSBAC_LIST_TRANS
07346 for (i=0; i<list->nr_hashes; i++) {
07347 if (list->hashed[i].ta_copied) {
07348 if (ta_number) {
07349 if (list->hashed[i].ta_copied == ta_number) {
07350 ta_remove_all_items(list, i);
07351 if (!list->hashed[i].head) {
07352 list->hashed[i].ta_copied = 0;
07353 }
07354 } else {
07355 rsbac_write_unlock(&list->lock,
07356 &lock_flags);
07357 rsbac_read_unlock(®_head.lock,
07358 &rlock_flags);
07359 return -RSBAC_EBUSY;
07360 }
07361 } else
07362 ta_remove_all_items(list, i);
07363 } else {
07364 if (ta_number) {
07365 if (list->hashed[i].head) {
07366 list->hashed[i].ta_head = NULL;
07367 list->hashed[i].ta_tail = NULL;
07368 list->hashed[i].ta_curr = NULL;
07369 list->hashed[i].ta_count = 0;
07370 list->hashed[i].ta_copied = ta_number;
07371 }
07372 }
07373 }
07374 }
07375
07376 if (!ta_number)
07377 #endif
07378 for (i=0; i<list->nr_hashes; i++)
07379 if (list->hashed[i].head) {
07380 remove_all_items(list, i);
07381 touch(list);
07382 list->dirty = TRUE;
07383 }
07384 rsbac_write_unlock(&list->lock, &lock_flags);
07385 rsbac_read_unlock(®_head.lock, &rlock_flags);
07386 return 0;
07387 }
07388
07389 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07390 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_count);
07391 #endif
07392 int rsbac_ta_list_lol_subremove_count(rsbac_list_ta_number_t ta_number,
07393 rsbac_list_handle_t handle,
07394 void *desc, u_long count)
07395 {
07396 struct rsbac_list_lol_reg_item_t *list;
07397 struct rsbac_list_lol_item_t *sublist;
07398 u_long lock_flags, rlock_flags;
07399 u_int hash = 0;
07400
07401 if (!count)
07402 return 0;
07403 if (!handle)
07404 return -RSBAC_EINVALIDLIST;
07405 if (!desc)
07406 return -RSBAC_EINVALIDVALUE;
07407 if (!list_initialized)
07408 return -RSBAC_ENOTINITIALIZED;
07409
07410 list = (struct rsbac_list_lol_reg_item_t *) handle;
07411 if (list->self != list)
07412 return -RSBAC_EINVALIDLIST;
07413
07414 #ifdef CONFIG_RSBAC_LIST_TRANS
07415 if (ta_number) {
07416 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07417 return -RSBAC_EINVALIDTRANSACTION;
07418 }
07419 #endif
07420
07421 if(list->hash_function)
07422 hash = list->hash_function(desc, list->nr_hashes);
07423
07424 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07425
07426
07427
07428
07429
07430 rsbac_write_lock(&list->lock, &lock_flags);
07431 #ifdef CONFIG_RSBAC_LIST_TRANS
07432 if (list->hashed[hash].ta_copied) {
07433 sublist = ta_lookup_lol_item(list->hashed[hash].ta_copied, list, desc);
07434 if (sublist) {
07435 if (sublist->max_age
07436 && (sublist->max_age <= RSBAC_CURRENT_TIME)
07437 ) {
07438 ta_do_remove_lol_item(list, sublist, hash);
07439 } else {
07440 if (ta_number
07441 && (list->hashed[hash].ta_copied != ta_number)) {
07442 rsbac_write_unlock(&list->lock,
07443 &lock_flags);
07444 rsbac_read_unlock(&lol_reg_head.
07445 lock,
07446 &rlock_flags);
07447 return -RSBAC_EBUSY;
07448 }
07449 while (sublist->head && (count > 0)) {
07450 do_remove_lol_subitem(sublist,
07451 sublist->head);
07452 count--;
07453 }
07454 if (!sublist->count
07455 && ((list->def_data
07456 && !memcmp(((char *) sublist) +
07457 sizeof(*sublist) +
07458 list->info.desc_size,
07459 list->def_data,
07460 list->info.data_size)
07461 )
07462 || (!list->info.data_size
07463 && (list->
07464 flags &
07465 RSBAC_LIST_DEF_DATA)
07466 )
07467 )
07468 ) {
07469 ta_do_remove_lol_item(list,
07470 sublist,
07471 hash);
07472 }
07473 }
07474 }
07475 } else {
07476 if (ta_number && lookup_lol_item(list, desc)) {
07477 ta_lol_copy(ta_number, list, hash);
07478 ta_remove_lol_item(ta_number, list, desc);
07479 }
07480 }
07481 if (!ta_number)
07482 #endif
07483 {
07484 sublist = lookup_lol_item(list, desc);
07485 if (sublist) {
07486 if (sublist->max_age
07487 && (sublist->max_age <= RSBAC_CURRENT_TIME)
07488 ) {
07489 do_remove_lol_item(list, sublist, hash);
07490 lol_touch(list);
07491 list->dirty = TRUE;
07492 } else {
07493 while (sublist->head && (count > 0)) {
07494 do_remove_lol_subitem(sublist,
07495 sublist->head);
07496 count--;
07497 }
07498 lol_touch(list);
07499 list->dirty = TRUE;
07500 if (!sublist->count
07501 && ((list->def_data
07502 && !memcmp(((char *) sublist) +
07503 sizeof(*sublist) +
07504 list->info.desc_size,
07505 list->def_data,
07506 list->info.data_size)
07507 )
07508 || (!list->info.data_size
07509 && (list->
07510 flags &
07511 RSBAC_LIST_DEF_DATA)
07512 )
07513 )
07514 ) {
07515 do_remove_lol_item(list, sublist, hash);
07516 }
07517 }
07518 }
07519 }
07520 rsbac_write_unlock(&list->lock, &lock_flags);
07521 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07522 return 0;
07523 }
07524
07525
07526 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07527 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove);
07528 #endif
07529 int rsbac_ta_list_lol_subremove(rsbac_list_ta_number_t ta_number,
07530 rsbac_list_handle_t handle,
07531 void *desc, void *subdesc)
07532 {
07533 struct rsbac_list_lol_reg_item_t *list;
07534 struct rsbac_list_lol_item_t *sublist;
07535 u_long lock_flags, rlock_flags;
07536 u_int hash = 0;
07537
07538 if (!handle)
07539 return -RSBAC_EINVALIDLIST;
07540 if (!desc || !subdesc)
07541 return -RSBAC_EINVALIDVALUE;
07542 if (!list_initialized)
07543 return -RSBAC_ENOTINITIALIZED;
07544
07545 list = (struct rsbac_list_lol_reg_item_t *) handle;
07546 if (list->self != list)
07547 return -RSBAC_EINVALIDLIST;
07548
07549 #ifdef CONFIG_RSBAC_LIST_TRANS
07550 if (ta_number) {
07551 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07552 return -RSBAC_EINVALIDTRANSACTION;
07553 }
07554 #endif
07555
07556 if(list->hash_function)
07557 hash = list->hash_function(desc, list->nr_hashes);
07558 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07559
07560
07561
07562
07563
07564 rsbac_write_lock(&list->lock, &lock_flags);
07565 #ifdef CONFIG_RSBAC_LIST_TRANS
07566 if (list->hashed[hash].ta_copied) {
07567 sublist = ta_lookup_lol_item(list->hashed[hash].ta_copied, list, desc);
07568 if (sublist) {
07569 if (sublist->max_age
07570 && (sublist->max_age <= RSBAC_CURRENT_TIME)
07571 ) {
07572 ta_do_remove_lol_item(list, sublist, hash);
07573 } else {
07574 if (ta_number
07575 && (list->hashed[hash].ta_copied != ta_number)) {
07576 rsbac_write_unlock(&list->lock,
07577 &lock_flags);
07578 rsbac_read_unlock(&lol_reg_head.
07579 lock,
07580 &rlock_flags);
07581 return -RSBAC_EBUSY;
07582 }
07583 if (lookup_lol_subitem
07584 (list, sublist, subdesc))
07585 remove_lol_subitem(list, sublist,
07586 subdesc);
07587 if (!sublist->count
07588 &&
07589 ((list->def_data
07590 && !memcmp(((char *) sublist) +
07591 sizeof(*sublist) +
07592 list->info.desc_size,
07593 list->def_data,
07594 list->info.data_size)
07595 )
07596 || (!list->info.data_size
07597 && (list->
07598 flags & RSBAC_LIST_DEF_DATA)
07599 )
07600 )
07601 ) {
07602 ta_do_remove_lol_item(list,
07603 sublist,
07604 hash);
07605 }
07606 }
07607 }
07608 } else {
07609 if (ta_number && lookup_lol_item(list, desc)) {
07610 ta_lol_copy(ta_number, list, hash);
07611 ta_remove_lol_item(ta_number, list, desc);
07612 }
07613 }
07614 if (!ta_number)
07615 #endif
07616 {
07617 sublist = lookup_lol_item(list, desc);
07618 if (sublist) {
07619 if (sublist->max_age
07620 && (sublist->max_age <= RSBAC_CURRENT_TIME)
07621 ) {
07622 do_remove_lol_item(list, sublist, hash);
07623 lol_touch(list);
07624 list->dirty = TRUE;
07625 } else {
07626 if (lookup_lol_subitem(list, sublist, subdesc)) {
07627 remove_lol_subitem(list, sublist,
07628 subdesc);
07629 lol_touch(list);
07630 list->dirty = TRUE;
07631 }
07632 if (!sublist->count
07633 && ((list->def_data
07634 && !memcmp(((char *) sublist) +
07635 sizeof(*sublist) +
07636 list->info.desc_size,
07637 list->def_data,
07638 list->info.data_size)
07639 )
07640 || (!list->info.data_size
07641 && (list->
07642 flags &
07643 RSBAC_LIST_DEF_DATA)
07644 )
07645 )
07646 ) {
07647 do_remove_lol_item(list, sublist, hash);
07648 lol_touch(list);
07649 list->dirty = TRUE;
07650 }
07651 }
07652 }
07653 }
07654 rsbac_write_unlock(&list->lock, &lock_flags);
07655 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07656 return 0;
07657 }
07658
07659
07660 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07661 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_from_all);
07662 #endif
07663 int rsbac_ta_list_lol_subremove_from_all(rsbac_list_ta_number_t ta_number,
07664 rsbac_list_handle_t handle,
07665 void *subdesc)
07666 {
07667 struct rsbac_list_lol_reg_item_t *list;
07668 struct rsbac_list_lol_item_t *sublist;
07669 u_long lock_flags, rlock_flags;
07670 int i;
07671
07672 if (!handle)
07673 return -RSBAC_EINVALIDLIST;
07674 if (!subdesc)
07675 return -RSBAC_EINVALIDVALUE;
07676 if (!list_initialized)
07677 return -RSBAC_ENOTINITIALIZED;
07678
07679 list = (struct rsbac_list_lol_reg_item_t *) handle;
07680 if (list->self != list)
07681 return -RSBAC_EINVALIDLIST;
07682
07683 #ifdef CONFIG_RSBAC_LIST_TRANS
07684 if (ta_number) {
07685 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07686 return -RSBAC_EINVALIDTRANSACTION;
07687 }
07688 #endif
07689
07690 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07691
07692
07693
07694 rsbac_write_lock(&list->lock, &lock_flags);
07695 #ifdef CONFIG_RSBAC_LIST_TRANS
07696 for (i=0; i<list->nr_hashes; i++) {
07697 if (list->hashed[i].ta_copied) {
07698 if (ta_number && (list->hashed[i].ta_copied != ta_number)) {
07699 rsbac_write_unlock(&list->lock, &lock_flags);
07700 rsbac_read_unlock(&lol_reg_head.lock,
07701 &rlock_flags);
07702 return -RSBAC_EBUSY;
07703 }
07704 sublist = list->hashed[i].head;
07705 while (sublist) {
07706 remove_lol_subitem(list, sublist, subdesc);
07707 sublist = sublist->next;
07708 }
07709 } else {
07710 if (ta_number) {
07711 ta_lol_copy(ta_number, list, i);
07712 sublist = list->hashed[i].head;
07713 while (sublist) {
07714 remove_lol_subitem(list, sublist, subdesc);
07715 sublist = sublist->next;
07716 }
07717 }
07718 }
07719 }
07720 if (!ta_number)
07721 #endif
07722 {
07723 for (i=0; i<list->nr_hashes; i++) {
07724 sublist = list->hashed[i].head;
07725 while (sublist) {
07726 if (lookup_lol_subitem(list, sublist, subdesc)) {
07727 remove_lol_subitem(list, sublist, subdesc);
07728 lol_touch(list);
07729 list->dirty = TRUE;
07730 }
07731 sublist = sublist->next;
07732 }
07733 }
07734 }
07735 rsbac_write_unlock(&list->lock, &lock_flags);
07736 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07737 return 0;
07738 }
07739
07740
07741 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07742 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_all);
07743 #endif
07744 int rsbac_ta_list_lol_subremove_all(rsbac_list_ta_number_t ta_number,
07745 rsbac_list_handle_t handle, void *desc)
07746 {
07747 struct rsbac_list_lol_reg_item_t *list;
07748 struct rsbac_list_lol_item_t *sublist;
07749 u_long lock_flags, rlock_flags;
07750 u_int hash = 0;
07751
07752 if (!handle)
07753 return -RSBAC_EINVALIDLIST;
07754 if (!list_initialized)
07755 return -RSBAC_ENOTINITIALIZED;
07756
07757 list = (struct rsbac_list_lol_reg_item_t *) handle;
07758 if (list->self != list)
07759 return -RSBAC_EINVALIDLIST;
07760
07761 #ifdef CONFIG_RSBAC_LIST_TRANS
07762 if (ta_number) {
07763 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07764 return -RSBAC_EINVALIDTRANSACTION;
07765 }
07766 #endif
07767
07768 if(list->hash_function)
07769 hash = list->hash_function(desc, list->nr_hashes);
07770 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07771
07772
07773
07774
07775 rsbac_write_lock(&list->lock, &lock_flags);
07776 #ifdef CONFIG_RSBAC_LIST_TRANS
07777 if (list->hashed[hash].ta_copied) {
07778 sublist = ta_lookup_lol_item(list->hashed[hash].ta_copied, list, desc);
07779 if (sublist) {
07780 if (sublist->max_age
07781 && (sublist->max_age <= RSBAC_CURRENT_TIME)
07782 ) {
07783 ta_do_remove_lol_item(list, sublist, hash);
07784 } else {
07785 if (ta_number
07786 && (list->hashed[hash].ta_copied != ta_number)) {
07787 rsbac_write_unlock(&list->lock,
07788 &lock_flags);
07789 rsbac_read_unlock(&lol_reg_head.
07790 lock,
07791 &rlock_flags);
07792 return -RSBAC_EBUSY;
07793 }
07794 remove_all_lol_subitems(sublist);
07795 if ((list->def_data
07796 && !memcmp(((char *) sublist) +
07797 sizeof(*sublist) +
07798 list->info.desc_size,
07799 list->def_data,
07800 list->info.data_size)
07801 )
07802 || (!list->info.data_size
07803 && (list->
07804 flags & RSBAC_LIST_DEF_DATA)
07805 )
07806
07807 ) {
07808 ta_do_remove_lol_item(list,
07809 sublist,
07810 hash);
07811 }
07812 }
07813 }
07814 } else {
07815 if (ta_number && lookup_lol_item(list, desc)) {
07816 ta_lol_copy(ta_number, list, hash);
07817 sublist =
07818 ta_lookup_lol_item(ta_number, list, desc);
07819 if (sublist)
07820 remove_all_lol_subitems(sublist);
07821 }
07822 }
07823 if (!ta_number)
07824 #endif
07825 {
07826 sublist = lookup_lol_item(list, desc);
07827 if (sublist && sublist->head) {
07828 remove_all_lol_subitems(sublist);
07829 lol_touch(list);
07830 list->dirty = TRUE;
07831 }
07832 }
07833 rsbac_write_unlock(&list->lock, &lock_flags);
07834 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07835 return 0;
07836 }
07837
07838 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07839 EXPORT_SYMBOL(rsbac_ta_list_lol_remove);
07840 #endif
07841 int rsbac_ta_list_lol_remove(rsbac_list_ta_number_t ta_number,
07842 rsbac_list_handle_t handle, void *desc)
07843 {
07844 struct rsbac_list_lol_reg_item_t *list;
07845 u_long lock_flags, rlock_flags;
07846 u_int hash = 0;
07847
07848 if (!handle)
07849 return -RSBAC_EINVALIDLIST;
07850 if (!desc)
07851 return -RSBAC_EINVALIDVALUE;
07852 if (!list_initialized)
07853 return -RSBAC_ENOTINITIALIZED;
07854
07855 list = (struct rsbac_list_lol_reg_item_t *) handle;
07856 if (list->self != list)
07857 return -RSBAC_EINVALIDLIST;
07858
07859 #ifdef CONFIG_RSBAC_LIST_TRANS
07860 if (ta_number) {
07861 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07862 return -RSBAC_EINVALIDTRANSACTION;
07863 }
07864 #endif
07865
07866 if(list->hash_function)
07867 hash = list->hash_function(desc, list->nr_hashes);
07868 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07869
07870
07871
07872
07873 rsbac_write_lock(&list->lock, &lock_flags);
07874 #ifdef CONFIG_RSBAC_LIST_TRANS
07875 if (list->hashed[hash].ta_copied) {
07876 if (ta_number) {
07877 if (ta_lookup_lol_item
07878 (list->hashed[hash].ta_copied, list, desc)) {
07879 if (list->hashed[hash].ta_copied != ta_number) {
07880 rsbac_write_unlock(&list->lock,
07881 &lock_flags);
07882 rsbac_read_unlock(&lol_reg_head.
07883 lock,
07884 &rlock_flags);
07885 return -RSBAC_EBUSY;
07886 } else
07887 ta_remove_lol_item(ta_number, list,
07888 desc);
07889 }
07890 } else
07891 ta_remove_lol_item(list->hashed[hash].ta_copied, list, desc);
07892 } else {
07893 if (ta_number && lookup_lol_item(list, desc)) {
07894 ta_lol_copy(ta_number, list, hash);
07895 ta_remove_lol_item(ta_number, list, desc);
07896 }
07897 }
07898 if (!ta_number)
07899 #endif
07900 {
07901 if (lookup_lol_item(list, desc)) {
07902 remove_lol_item(list, desc);
07903 lol_touch(list);
07904 list->dirty = TRUE;
07905 }
07906 }
07907 rsbac_write_unlock(&list->lock, &lock_flags);
07908 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07909 return 0;
07910 }
07911
07912
07913 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07914 EXPORT_SYMBOL(rsbac_ta_list_lol_remove_all);
07915 #endif
07916 int rsbac_ta_list_lol_remove_all(rsbac_list_ta_number_t ta_number,
07917 rsbac_list_handle_t handle)
07918 {
07919 struct rsbac_list_lol_reg_item_t *list;
07920 u_long lock_flags, rlock_flags;
07921 int i;
07922
07923 if (!handle)
07924 return -RSBAC_EINVALIDLIST;
07925 if (!list_initialized)
07926 return -RSBAC_ENOTINITIALIZED;
07927
07928 list = (struct rsbac_list_lol_reg_item_t *) handle;
07929 if (list->self != list)
07930 return -RSBAC_EINVALIDLIST;
07931
07932 #ifdef CONFIG_RSBAC_LIST_TRANS
07933 if (ta_number) {
07934 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07935 return -RSBAC_EINVALIDTRANSACTION;
07936 }
07937 #endif
07938
07939 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07940
07941
07942
07943
07944 rsbac_write_lock(&list->lock, &lock_flags);
07945 #ifdef CONFIG_RSBAC_LIST_TRANS
07946 for (i=0; i<list->nr_hashes; i++) {
07947 if (list->hashed[i].ta_copied) {
07948 if (ta_number) {
07949 if (list->hashed[i].ta_copied == ta_number) {
07950 ta_remove_all_lol_items(list, i);
07951 if (!list->hashed[i].head) {
07952 list->hashed[i].ta_copied = 0;
07953 }
07954 } else {
07955 rsbac_write_unlock(&list->lock,
07956 &lock_flags);
07957 rsbac_read_unlock(&lol_reg_head.lock,
07958 &rlock_flags);
07959 return -RSBAC_EBUSY;
07960 }
07961 } else
07962 ta_remove_all_lol_items(list, i);
07963 } else {
07964 if (ta_number) {
07965 if (list->hashed[i].head) {
07966 list->hashed[i].ta_head = NULL;
07967 list->hashed[i].ta_tail = NULL;
07968 list->hashed[i].ta_curr = NULL;
07969 list->hashed[i].ta_count = 0;
07970 list->hashed[i].ta_copied = ta_number;
07971 }
07972 }
07973 }
07974 }
07975
07976 if (!ta_number)
07977 #endif
07978 for (i=0; i<list->nr_hashes; i++) {
07979 if (list->hashed[i].head) {
07980 remove_all_lol_items(list, i);
07981 lol_touch(list);
07982 list->dirty = TRUE;
07983 }
07984 }
07985 rsbac_write_unlock(&list->lock, &lock_flags);
07986 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07987 return 0;
07988 }
07989
07990
07991
07992
07993 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07994 EXPORT_SYMBOL(rsbac_ta_list_get_data_ttl);
07995 #endif
07996 int rsbac_ta_list_get_data_ttl(rsbac_list_ta_number_t ta_number,
07997 rsbac_list_handle_t handle,
07998 rsbac_time_t * ttl_p,
07999 void *desc, void *data)
08000 {
08001 struct rsbac_list_reg_item_t *list;
08002 struct rsbac_list_item_t *item_p;
08003 u_long lock_flags, rlock_flags;
08004 int err = 0;
08005 #ifdef CONFIG_RSBAC_LIST_TRANS
08006 u_int hash = 0;
08007 #endif
08008
08009 if (!handle)
08010 return -RSBAC_EINVALIDLIST;
08011 if (!desc)
08012 return -RSBAC_EINVALIDVALUE;
08013 if (!list_initialized)
08014 return -RSBAC_ENOTINITIALIZED;
08015
08016 list = (struct rsbac_list_reg_item_t *) handle;
08017 if (list->self != list)
08018 return -RSBAC_EINVALIDLIST;
08019
08020 #ifdef CONFIG_RSBAC_LIST_TRANS
08021 if (ta_number) {
08022 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08023 return -RSBAC_EINVALIDTRANSACTION;
08024 if(list->hash_function)
08025 hash = list->hash_function(desc, list->nr_hashes);
08026 }
08027 #endif
08028
08029 rsbac_read_lock(®_head.lock, &rlock_flags);
08030
08031
08032
08033
08034 if (data && !list->info.data_size) {
08035 rsbac_read_unlock(®_head.lock, &rlock_flags);
08036 return -RSBAC_EINVALIDREQUEST;
08037 }
08038
08039 rsbac_read_lock(&list->lock, &lock_flags);
08040 #ifdef CONFIG_RSBAC_LIST_TRANS
08041 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08042 item_p = ta_lookup_item(ta_number, list, desc);
08043 else
08044 #endif
08045 item_p = lookup_item(list, desc);
08046 if (item_p
08047 && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
08048 )
08049 ) {
08050 if (ttl_p) {
08051 if (item_p->max_age)
08052 *ttl_p =
08053 item_p->max_age - RSBAC_CURRENT_TIME;
08054 else
08055 *ttl_p = 0;
08056 }
08057 if (data) {
08058 memcpy(data,
08059 ((char *) item_p) + sizeof(*item_p) +
08060 list->info.desc_size, list->info.data_size);
08061 }
08062 } else {
08063 if (!list->def_data)
08064 err = -RSBAC_ENOTFOUND;
08065 else {
08066 if (ttl_p)
08067 *ttl_p = 0;
08068 if (data)
08069 memcpy(data,
08070 list->def_data,
08071 list->info.data_size);
08072 }
08073 }
08074 rsbac_read_unlock(&list->lock, &lock_flags);
08075 rsbac_read_unlock(®_head.lock, &rlock_flags);
08076 return err;
08077 }
08078
08079 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08080 EXPORT_SYMBOL(rsbac_ta_list_lol_get_max_subdesc);
08081 #endif
08082 int rsbac_ta_list_lol_get_max_subdesc(rsbac_list_ta_number_t ta_number,
08083 rsbac_list_handle_t handle,
08084 void *desc, void *subdesc)
08085 {
08086 struct rsbac_list_lol_reg_item_t *list;
08087 struct rsbac_list_lol_item_t *sublist;
08088 struct rsbac_list_item_t *item_p;
08089 u_long lock_flags, rlock_flags;
08090 int err = 0;
08091 #ifdef CONFIG_RSBAC_LIST_TRANS
08092 u_int hash = 0;
08093 #endif
08094
08095 if (!handle)
08096 return -RSBAC_EINVALIDLIST;
08097 if (!desc || !subdesc)
08098 return -RSBAC_EINVALIDVALUE;
08099 if (!list_initialized)
08100 return -RSBAC_ENOTINITIALIZED;
08101
08102 list = (struct rsbac_list_lol_reg_item_t *) handle;
08103 if (list->self != list)
08104 return -RSBAC_EINVALIDLIST;
08105
08106 #ifdef CONFIG_RSBAC_LIST_TRANS
08107 if (ta_number) {
08108 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08109 return -RSBAC_EINVALIDTRANSACTION;
08110 if(list->hash_function)
08111 hash = list->hash_function(desc, list->nr_hashes);
08112 }
08113 #endif
08114
08115 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08116
08117
08118
08119
08120
08121 rsbac_read_lock(&list->lock, &lock_flags);
08122
08123 #ifdef CONFIG_RSBAC_LIST_TRANS
08124 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08125 sublist = ta_lookup_lol_item(ta_number, list, desc);
08126 else
08127 #endif
08128 sublist = lookup_lol_item(list, desc);
08129 if (sublist) {
08130 item_p = sublist->tail;
08131 while (item_p
08132 && item_p->max_age
08133 && (item_p->max_age > RSBAC_CURRENT_TIME)
08134 )
08135 item_p = item_p->prev;
08136 if (item_p)
08137 memcpy(subdesc, (char *) item_p + sizeof(*item_p),
08138 list->info.subdesc_size);
08139 else {
08140 memset(subdesc, 0, list->info.subdesc_size);
08141 err = -RSBAC_ENOTFOUND;
08142 }
08143 } else {
08144 if (!(list->flags & RSBAC_LIST_DEF_DATA))
08145 err = -RSBAC_ENOTFOUND;
08146 }
08147 rsbac_read_unlock(&list->lock, &lock_flags);
08148 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08149 return err;
08150 }
08151
08152 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08153 EXPORT_SYMBOL(rsbac_ta_list_lol_get_subdata_ttl);
08154 #endif
08155 int rsbac_ta_list_lol_get_subdata_ttl(rsbac_list_ta_number_t ta_number,
08156 rsbac_list_handle_t handle,
08157 rsbac_time_t * ttl_p,
08158 void *desc,
08159 void *subdesc, void *subdata)
08160 {
08161 struct rsbac_list_lol_reg_item_t *list;
08162 struct rsbac_list_lol_item_t *sublist;
08163 struct rsbac_list_item_t *item_p;
08164 u_long lock_flags, rlock_flags;
08165 int err = 0;
08166 #ifdef CONFIG_RSBAC_LIST_TRANS
08167 u_int hash = 0;
08168 #endif
08169
08170 if (!handle)
08171 return -RSBAC_EINVALIDLIST;
08172 if (!desc || !subdesc)
08173 return -RSBAC_EINVALIDVALUE;
08174 if (!list_initialized)
08175 return -RSBAC_ENOTINITIALIZED;
08176
08177 list = (struct rsbac_list_lol_reg_item_t *) handle;
08178 if (list->self != list)
08179 return -RSBAC_EINVALIDLIST;
08180
08181 #ifdef CONFIG_RSBAC_LIST_TRANS
08182 if (ta_number) {
08183 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08184 return -RSBAC_EINVALIDTRANSACTION;
08185 if(list->hash_function)
08186 hash = list->hash_function(desc, list->nr_hashes);
08187 }
08188 #endif
08189
08190 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08191
08192
08193
08194 if (subdata && !list->info.subdata_size) {
08195 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08196 return -RSBAC_EINVALIDREQUEST;
08197 }
08198
08199 rsbac_read_lock(&list->lock, &lock_flags);
08200
08201 #ifdef CONFIG_RSBAC_LIST_TRANS
08202 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08203 sublist = ta_lookup_lol_item(ta_number, list, desc);
08204 else
08205 #endif
08206 sublist = lookup_lol_item(list, desc);
08207 if (sublist) {
08208 item_p = lookup_lol_subitem(list, sublist, subdesc);
08209 if (item_p
08210 && (!item_p->max_age
08211 || (item_p->max_age > RSBAC_CURRENT_TIME)
08212 )
08213 ) {
08214 if (ttl_p) {
08215 if (item_p->max_age)
08216 *ttl_p =
08217 item_p->max_age -
08218 RSBAC_CURRENT_TIME;
08219 else
08220 *ttl_p = 0;
08221 }
08222 if (subdata) {
08223 memcpy(subdata,
08224 ((char *) item_p) +
08225 sizeof(*item_p) +
08226 list->info.subdesc_size,
08227 list->info.subdata_size);
08228 }
08229 } else {
08230 if (!list->def_subdata)
08231 err = -RSBAC_ENOTFOUND;
08232 else {
08233 if (ttl_p)
08234 *ttl_p = 0;
08235 if (subdata)
08236 memcpy(subdata,
08237 list->def_subdata,
08238 list->info.subdata_size);
08239 }
08240 }
08241 } else {
08242 if (!list->def_subdata)
08243 err = -RSBAC_ENOTFOUND;
08244 else {
08245 if (ttl_p)
08246 *ttl_p = 0;
08247 if (subdata)
08248 memcpy(subdata,
08249 list->def_subdata,
08250 list->info.subdata_size);
08251 }
08252 }
08253 rsbac_read_unlock(&list->lock, &lock_flags);
08254 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08255 return err;
08256 }
08257
08258 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08259 EXPORT_SYMBOL(rsbac_ta_list_lol_get_data_ttl);
08260 #endif
08261 int rsbac_ta_list_lol_get_data_ttl(rsbac_list_ta_number_t ta_number,
08262 rsbac_list_handle_t handle,
08263 rsbac_time_t * ttl_p,
08264 void *desc, void *data)
08265 {
08266 struct rsbac_list_lol_reg_item_t *list;
08267 struct rsbac_list_lol_item_t *item_p;
08268 u_long lock_flags, rlock_flags;
08269 int err = 0;
08270 #ifdef CONFIG_RSBAC_LIST_TRANS
08271 u_int hash = 0;
08272 #endif
08273
08274 if (!handle)
08275 return -RSBAC_EINVALIDLIST;
08276 if (!desc)
08277 return -RSBAC_EINVALIDVALUE;
08278 if (!list_initialized)
08279 return -RSBAC_ENOTINITIALIZED;
08280
08281 list = (struct rsbac_list_lol_reg_item_t *) handle;
08282 if (list->self != list)
08283 return -RSBAC_EINVALIDLIST;
08284
08285 #ifdef CONFIG_RSBAC_LIST_TRANS
08286 if (ta_number) {
08287 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08288 return -RSBAC_EINVALIDTRANSACTION;
08289 if(list->hash_function)
08290 hash = list->hash_function(desc, list->nr_hashes);
08291 }
08292 #endif
08293
08294 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08295
08296
08297
08298 if (data && !list->info.data_size) {
08299 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08300 return -RSBAC_EINVALIDREQUEST;
08301 }
08302
08303 rsbac_read_lock(&list->lock, &lock_flags);
08304
08305 #ifdef CONFIG_RSBAC_LIST_TRANS
08306 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08307 item_p = ta_lookup_lol_item(ta_number, list, desc);
08308 else
08309 #endif
08310 item_p = lookup_lol_item(list, desc);
08311 if (item_p
08312 && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
08313 )
08314 ) {
08315 if (ttl_p) {
08316 if (item_p->max_age)
08317 *ttl_p =
08318 item_p->max_age - RSBAC_CURRENT_TIME;
08319 else
08320 *ttl_p = 0;
08321 }
08322 if (data) {
08323 memcpy(data,
08324 ((char *) item_p) + sizeof(*item_p) +
08325 list->info.desc_size, list->info.data_size);
08326 }
08327 } else {
08328 if (!list->def_data)
08329 err = -RSBAC_ENOTFOUND;
08330 else {
08331 if (ttl_p)
08332 *ttl_p = 0;
08333 if (data)
08334 memcpy(data,
08335 list->def_data,
08336 list->info.data_size);
08337 }
08338 }
08339 rsbac_read_unlock(&list->lock, &lock_flags);
08340 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08341 return err;
08342 }
08343
08344 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08345 EXPORT_SYMBOL(rsbac_ta_list_get_max_desc);
08346 #endif
08347 int rsbac_ta_list_get_max_desc(rsbac_list_ta_number_t ta_number,
08348 rsbac_list_handle_t handle, void *desc)
08349 {
08350 struct rsbac_list_reg_item_t *list;
08351 struct rsbac_list_item_t *item_p = NULL;
08352 struct rsbac_list_item_t *tmp_item_p;
08353 u_long lock_flags, rlock_flags;
08354 int err = 0;
08355 int i;
08356
08357 if (!handle)
08358 return -RSBAC_EINVALIDLIST;
08359 if (!list_initialized)
08360 return -RSBAC_ENOTINITIALIZED;
08361
08362 list = (struct rsbac_list_reg_item_t *) handle;
08363 if (list->self != list)
08364 return -RSBAC_EINVALIDLIST;
08365
08366 #ifdef CONFIG_RSBAC_LIST_TRANS
08367 if (ta_number) {
08368 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08369 return -RSBAC_EINVALIDTRANSACTION;
08370 }
08371 #endif
08372
08373 rsbac_read_lock(®_head.lock, &rlock_flags);
08374
08375
08376
08377 rsbac_read_lock(&list->lock, &lock_flags);
08378 for (i=0; i<list->nr_hashes; i++) {
08379 #ifdef CONFIG_RSBAC_LIST_TRANS
08380 if (ta_number && (list->hashed[i].ta_copied == ta_number))
08381 tmp_item_p = list->hashed[i].ta_tail;
08382 else
08383 #endif
08384 tmp_item_p = list->hashed[i].tail;
08385 while (tmp_item_p
08386 && tmp_item_p->max_age && (tmp_item_p->max_age > RSBAC_CURRENT_TIME)
08387 )
08388 tmp_item_p = tmp_item_p->prev;
08389 if(tmp_item_p) {
08390 if(list->compare) {
08391 if(!item_p || list->compare(&tmp_item_p[1], &item_p[1]) > 0)
08392 item_p = tmp_item_p;
08393 } else {
08394 if(!item_p || memcmp(&tmp_item_p[1], &item_p[1], list->info.desc_size) > 0)
08395 item_p = tmp_item_p;
08396 }
08397 }
08398 }
08399 if (item_p)
08400 memcpy(desc, (char *) item_p + sizeof(*item_p),
08401 list->info.desc_size);
08402 else {
08403 memset(desc, 0, list->info.desc_size);
08404 err = -RSBAC_ENOTFOUND;
08405 }
08406 rsbac_read_unlock(&list->lock, &lock_flags);
08407 rsbac_read_unlock(®_head.lock, &rlock_flags);
08408 return err;
08409 }
08410
08411 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08412 EXPORT_SYMBOL(rsbac_ta_list_get_next_desc);
08413 #endif
08414 int rsbac_ta_list_get_next_desc(rsbac_list_ta_number_t ta_number,
08415 rsbac_list_handle_t handle,
08416 void *old_desc, void *next_desc)
08417 {
08418 struct rsbac_list_reg_item_t *list;
08419 struct rsbac_list_item_t *item_p;
08420 u_long lock_flags, rlock_flags;
08421 u_int hash = 0;
08422
08423 if (!handle)
08424 return -RSBAC_EINVALIDLIST;
08425 if (!list_initialized)
08426 return -RSBAC_ENOTINITIALIZED;
08427 if (!next_desc)
08428 return -RSBAC_EINVALIDPOINTER;
08429
08430 list = (struct rsbac_list_reg_item_t *) handle;
08431 if (list->self != list)
08432 return -RSBAC_EINVALIDLIST;
08433
08434 #ifdef CONFIG_RSBAC_LIST_TRANS
08435 if (ta_number) {
08436 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08437 return -RSBAC_EINVALIDTRANSACTION;
08438 }
08439 #endif
08440
08441 rsbac_read_lock(®_head.lock, &rlock_flags);
08442
08443
08444
08445 rsbac_read_lock(&list->lock, &lock_flags);
08446 if (old_desc) {
08447 if(list->hash_function)
08448 hash = list->hash_function(old_desc, list->nr_hashes);
08449 #ifdef CONFIG_RSBAC_LIST_TRANS
08450 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08451 item_p = ta_lookup_item(ta_number, list, old_desc);
08452 else
08453 #endif
08454 item_p = lookup_item(list, old_desc);
08455 if(item_p) {
08456 item_p = item_p->next;
08457 while (item_p
08458 && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
08459 ) {
08460 item_p = item_p->next;
08461 }
08462 hash++;
08463 } else
08464 hash = 0;
08465 } else
08466 item_p = NULL;
08467 while (!item_p && (hash < list->nr_hashes)) {
08468 #ifdef CONFIG_RSBAC_LIST_TRANS
08469 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08470 item_p = list->hashed[hash].ta_head;
08471 else
08472 #endif
08473 item_p = list->hashed[hash].head;
08474 while (item_p
08475 && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
08476 ) {
08477 item_p = item_p->next;
08478 }
08479 hash++;
08480 }
08481 if (item_p) {
08482 memcpy(next_desc, (char *) item_p + sizeof(*item_p),
08483 list->info.desc_size);
08484 }
08485 rsbac_read_unlock(&list->lock, &lock_flags);
08486 rsbac_read_unlock(®_head.lock, &rlock_flags);
08487 if (item_p)
08488 return 0;
08489 else
08490 return -RSBAC_ENOTFOUND;
08491 }
08492
08493 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08494 EXPORT_SYMBOL(rsbac_ta_list_lol_get_next_desc);
08495 #endif
08496 int rsbac_ta_list_lol_get_next_desc(rsbac_list_ta_number_t ta_number,
08497 rsbac_list_handle_t handle,
08498 void *old_desc, void *next_desc)
08499 {
08500 struct rsbac_list_lol_reg_item_t *list;
08501 struct rsbac_list_lol_item_t *item_p;
08502 u_long lock_flags, rlock_flags;
08503 u_int hash = 0;
08504
08505 if (!handle)
08506 return -RSBAC_EINVALIDLIST;
08507 if (!list_initialized)
08508 return -RSBAC_ENOTINITIALIZED;
08509 if (!next_desc)
08510 return -RSBAC_EINVALIDPOINTER;
08511
08512 list = (struct rsbac_list_lol_reg_item_t *) handle;
08513 if (list->self != list)
08514 return -RSBAC_EINVALIDLIST;
08515
08516 #ifdef CONFIG_RSBAC_LIST_TRANS
08517 if (ta_number) {
08518 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08519 return -RSBAC_EINVALIDTRANSACTION;
08520 }
08521 #endif
08522
08523 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08524
08525
08526
08527 rsbac_read_lock(&list->lock, &lock_flags);
08528 if (old_desc) {
08529 if(list->hash_function)
08530 hash = list->hash_function(old_desc, list->nr_hashes);
08531 #ifdef CONFIG_RSBAC_LIST_TRANS
08532 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08533 item_p = ta_lookup_lol_item(ta_number, list, old_desc);
08534 else
08535 #endif
08536 item_p = lookup_lol_item(list, old_desc);
08537 if(item_p) {
08538 item_p = item_p->next;
08539 while (item_p
08540 && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
08541 ) {
08542 item_p = item_p->next;
08543 }
08544 hash++;
08545 } else
08546 hash = 0;
08547 } else
08548 item_p = NULL;
08549 while (!item_p && (hash < list->nr_hashes)) {
08550 #ifdef CONFIG_RSBAC_LIST_TRANS
08551 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08552 item_p = list->hashed[hash].ta_head;
08553 else
08554 #endif
08555 item_p = list->hashed[hash].head;
08556 while (item_p
08557 && item_p->max_age && (item_p->max_age > RSBAC_CURRENT_TIME)
08558 ) {
08559 item_p = item_p->next;
08560 }
08561 hash++;
08562 }
08563 if (item_p) {
08564 memcpy(next_desc, (char *) item_p + sizeof(*item_p),
08565 list->info.desc_size);
08566 }
08567 rsbac_read_unlock(&list->lock, &lock_flags);
08568 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08569 if (item_p)
08570 return 0;
08571 else
08572 return -RSBAC_ENOTFOUND;
08573 }
08574
08575
08576
08577
08578
08579
08580
08581
08582
08583 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08584 EXPORT_SYMBOL(rsbac_ta_list_get_desc);
08585 #endif
08586 int rsbac_ta_list_get_desc(rsbac_list_ta_number_t ta_number,
08587 rsbac_list_handle_t handle,
08588 void *desc,
08589 void *data,
08590 rsbac_list_data_compare_function_t compare)
08591 {
08592 struct rsbac_list_reg_item_t *list;
08593 struct rsbac_list_item_t *item_p;
08594 u_long lock_flags, rlock_flags;
08595 int err = 0;
08596
08597 if (!handle)
08598 return -RSBAC_EINVALIDLIST;
08599 if (!desc || !data)
08600 return -RSBAC_EINVALIDVALUE;
08601 if (!list_initialized)
08602 return -RSBAC_ENOTINITIALIZED;
08603
08604 list = (struct rsbac_list_reg_item_t *) handle;
08605 if (list->self != list)
08606 return -RSBAC_EINVALIDLIST;
08607
08608 #ifdef CONFIG_RSBAC_LIST_TRANS
08609 if (ta_number) {
08610 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08611 return -RSBAC_EINVALIDTRANSACTION;
08612 }
08613 #endif
08614
08615 rsbac_read_lock(®_head.lock, &rlock_flags);
08616
08617
08618
08619 if (!list->info.data_size) {
08620 rsbac_read_unlock(®_head.lock, &rlock_flags);
08621 return -RSBAC_EINVALIDREQUEST;
08622 }
08623
08624 rsbac_read_lock(&list->lock, &lock_flags);
08625
08626 #ifdef CONFIG_RSBAC_LIST_TRANS
08627 item_p = ta_lookup_item_data(ta_number, list, data, compare);
08628 #else
08629 item_p = lookup_item_data(list, data, compare);
08630 #endif
08631 if (item_p) {
08632 memcpy(desc,
08633 ((char *) item_p) + sizeof(*item_p),
08634 list->info.desc_size);
08635 } else {
08636 err = -RSBAC_ENOTFOUND;
08637 }
08638 rsbac_read_unlock(&list->lock, &lock_flags);
08639 rsbac_read_unlock(®_head.lock, &rlock_flags);
08640 return err;
08641 }
08642
08643 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08644 EXPORT_SYMBOL(rsbac_ta_list_lol_get_desc);
08645 #endif
08646 int rsbac_ta_list_lol_get_desc(rsbac_list_ta_number_t ta_number,
08647 rsbac_list_handle_t handle,
08648 void *desc,
08649 void *data,
08650 rsbac_list_data_compare_function_t compare)
08651 {
08652 struct rsbac_list_lol_reg_item_t *list;
08653 struct rsbac_list_lol_item_t *item_p;
08654 u_long lock_flags, rlock_flags;
08655 int err = 0;
08656
08657 if (!handle)
08658 return -RSBAC_EINVALIDLIST;
08659 if (!desc || !data)
08660 return -RSBAC_EINVALIDVALUE;
08661 if (!list_initialized)
08662 return -RSBAC_ENOTINITIALIZED;
08663
08664 list = (struct rsbac_list_lol_reg_item_t *) handle;
08665 if (list->self != list)
08666 return -RSBAC_EINVALIDLIST;
08667
08668 #ifdef CONFIG_RSBAC_LIST_TRANS
08669 if (ta_number) {
08670 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08671 return -RSBAC_EINVALIDTRANSACTION;
08672 }
08673 #endif
08674
08675 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08676
08677
08678
08679 if (!list->info.data_size) {
08680 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08681 return -RSBAC_EINVALIDREQUEST;
08682 }
08683
08684 rsbac_read_lock(&list->lock, &lock_flags);
08685
08686 #ifdef CONFIG_RSBAC_LIST_TRANS
08687 item_p = ta_lookup_lol_item_data(ta_number, list, data, compare);
08688 #else
08689 item_p = lookup_lol_item_data(list, data, compare);
08690 #endif
08691 if (item_p) {
08692 memcpy(desc,
08693 ((char *) item_p) + sizeof(*item_p),
08694 list->info.desc_size);
08695 } else {
08696 err = -RSBAC_ENOTFOUND;
08697 }
08698 rsbac_read_unlock(&list->lock, &lock_flags);
08699 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08700 return err;
08701 }
08702
08703
08704 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08705 EXPORT_SYMBOL(rsbac_ta_list_exist);
08706 #endif
08707 int rsbac_ta_list_exist(rsbac_list_ta_number_t ta_number,
08708 rsbac_list_handle_t handle, void *desc)
08709 {
08710 struct rsbac_list_reg_item_t *list;
08711 u_long lock_flags, rlock_flags;
08712 struct rsbac_list_item_t *item_p;
08713 int result;
08714 #ifdef CONFIG_RSBAC_LIST_TRANS
08715 u_int hash = 0;
08716 #endif
08717
08718 if (!handle || !desc)
08719 return FALSE;
08720 if (!list_initialized)
08721 return FALSE;
08722
08723 list = (struct rsbac_list_reg_item_t *) handle;
08724 if (list->self != list)
08725 return -RSBAC_EINVALIDLIST;
08726
08727 #ifdef CONFIG_RSBAC_LIST_TRANS
08728 if (ta_number) {
08729 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08730 return -RSBAC_EINVALIDTRANSACTION;
08731 if(list->hash_function)
08732 hash = list->hash_function(desc, list->nr_hashes);
08733 }
08734 #endif
08735
08736 rsbac_read_lock(®_head.lock, &rlock_flags);
08737
08738
08739
08740 rsbac_read_lock(&list->lock, &lock_flags);
08741
08742 #ifdef CONFIG_RSBAC_LIST_TRANS
08743 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08744 item_p = ta_lookup_item(ta_number, list, desc);
08745 else
08746 #endif
08747 item_p = lookup_item(list, desc);
08748 if (item_p
08749 && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
08750 )
08751 ) {
08752 result = TRUE;
08753 } else {
08754 result = FALSE;
08755 }
08756 rsbac_read_unlock(&list->lock, &lock_flags);
08757 rsbac_read_unlock(®_head.lock, &rlock_flags);
08758 return result;
08759 }
08760
08761
08762 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08763 EXPORT_SYMBOL(rsbac_ta_list_lol_subexist);
08764 #endif
08765 int rsbac_ta_list_lol_subexist(rsbac_list_ta_number_t ta_number,
08766 rsbac_list_handle_t handle,
08767 void *desc, void *subdesc)
08768 {
08769 struct rsbac_list_lol_reg_item_t *list;
08770 struct rsbac_list_lol_item_t *sublist;
08771 u_long lock_flags, rlock_flags;
08772 struct rsbac_list_item_t *item_p;
08773 int result;
08774 #ifdef CONFIG_RSBAC_LIST_TRANS
08775 u_int hash = 0;
08776 #endif
08777
08778 if (!handle || !desc || !subdesc)
08779 return FALSE;
08780 if (!list_initialized)
08781 return FALSE;
08782
08783 list = (struct rsbac_list_lol_reg_item_t *) handle;
08784 if (list->self != list)
08785 return -RSBAC_EINVALIDLIST;
08786
08787 #ifdef CONFIG_RSBAC_LIST_TRANS
08788 if (ta_number) {
08789 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08790 return -RSBAC_EINVALIDTRANSACTION;
08791 if(list->hash_function)
08792 hash = list->hash_function(desc, list->nr_hashes);
08793 }
08794 #endif
08795
08796 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08797
08798
08799
08800 rsbac_read_lock(&list->lock, &lock_flags);
08801
08802 #ifdef CONFIG_RSBAC_LIST_TRANS
08803 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08804 sublist = ta_lookup_lol_item(ta_number, list, desc);
08805 else
08806 #endif
08807 sublist = lookup_lol_item(list, desc);
08808 if (sublist) {
08809 item_p = lookup_lol_subitem(list, sublist, subdesc);
08810 if (item_p
08811 && (!item_p->max_age
08812 || (item_p->max_age > RSBAC_CURRENT_TIME)
08813 )
08814 ) {
08815 result = TRUE;
08816 } else {
08817 result = FALSE;
08818 }
08819 } else {
08820 result = FALSE;
08821 }
08822 rsbac_read_unlock(&list->lock, &lock_flags);
08823 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08824 return result;
08825 }
08826
08827 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08828 EXPORT_SYMBOL(rsbac_ta_list_lol_subexist_compare);
08829 #endif
08830 int rsbac_ta_list_lol_subexist_compare(rsbac_list_ta_number_t ta_number,
08831 rsbac_list_handle_t handle,
08832 void *desc,
08833 void *subdesc,
08834 rsbac_list_compare_function_t
08835 compare)
08836 {
08837 struct rsbac_list_lol_reg_item_t *list;
08838 struct rsbac_list_lol_item_t *sublist;
08839 u_long lock_flags, rlock_flags;
08840 struct rsbac_list_item_t *item_p;
08841 int result;
08842 #ifdef CONFIG_RSBAC_LIST_TRANS
08843 u_int hash = 0;
08844 #endif
08845
08846 if (!handle || !desc || !subdesc)
08847 return FALSE;
08848 if (!list_initialized)
08849 return FALSE;
08850
08851 if (!compare)
08852 return rsbac_list_lol_subexist(handle, desc, subdesc);
08853
08854 list = (struct rsbac_list_lol_reg_item_t *) handle;
08855 if (list->self != list)
08856 return -RSBAC_EINVALIDLIST;
08857
08858 #ifdef CONFIG_RSBAC_LIST_TRANS
08859 if (ta_number) {
08860 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08861 return -RSBAC_EINVALIDTRANSACTION;
08862 if(list->hash_function)
08863 hash = list->hash_function(desc, list->nr_hashes);
08864 }
08865 #endif
08866
08867 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08868
08869
08870
08871 rsbac_read_lock(&list->lock, &lock_flags);
08872
08873 #ifdef CONFIG_RSBAC_LIST_TRANS
08874 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08875 sublist = ta_lookup_lol_item(ta_number, list, desc);
08876 else
08877 #endif
08878 sublist = lookup_lol_item(list, desc);
08879 if (sublist) {
08880 item_p =
08881 lookup_lol_subitem_user_compare(list, sublist, subdesc,
08882 compare);
08883 if (item_p
08884 && (!item_p->max_age
08885 || (item_p->max_age > RSBAC_CURRENT_TIME)
08886 )
08887 ) {
08888 result = TRUE;
08889 } else {
08890 result = FALSE;
08891 }
08892 } else {
08893 result = FALSE;
08894 }
08895 rsbac_read_unlock(&list->lock, &lock_flags);
08896 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08897 return result;
08898 }
08899
08900 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08901 EXPORT_SYMBOL(rsbac_ta_list_lol_exist);
08902 #endif
08903 int rsbac_ta_list_lol_exist(rsbac_list_ta_number_t ta_number,
08904 rsbac_list_handle_t handle, void *desc)
08905 {
08906 struct rsbac_list_lol_reg_item_t *list;
08907 u_long lock_flags, rlock_flags;
08908 struct rsbac_list_lol_item_t *item_p;
08909 int result;
08910 #ifdef CONFIG_RSBAC_LIST_TRANS
08911 u_int hash = 0;
08912 #endif
08913
08914 if (!handle || !desc)
08915 return FALSE;
08916 if (!list_initialized)
08917 return FALSE;
08918
08919 list = (struct rsbac_list_lol_reg_item_t *) handle;
08920 if (list->self != list)
08921 return -RSBAC_EINVALIDLIST;
08922
08923 #ifdef CONFIG_RSBAC_LIST_TRANS
08924 if (ta_number) {
08925 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08926 return -RSBAC_EINVALIDTRANSACTION;
08927 if(list->hash_function)
08928 hash = list->hash_function(desc, list->nr_hashes);
08929 }
08930 #endif
08931
08932 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08933
08934
08935
08936 rsbac_read_lock(&list->lock, &lock_flags);
08937
08938 #ifdef CONFIG_RSBAC_LIST_TRANS
08939 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08940 item_p = ta_lookup_lol_item(ta_number, list, desc);
08941 else
08942 #endif
08943 item_p = lookup_lol_item(list, desc);
08944 if (item_p
08945 && (!item_p->max_age || (item_p->max_age > RSBAC_CURRENT_TIME)
08946 )
08947 ) {
08948 result = TRUE;
08949 } else {
08950 result = FALSE;
08951 }
08952 rsbac_read_unlock(&list->lock, &lock_flags);
08953 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08954 return result;
08955 }
08956
08957
08958
08959 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08960 EXPORT_SYMBOL(rsbac_ta_list_lol_subcount);
08961 #endif
08962 long rsbac_ta_list_lol_subcount(rsbac_list_ta_number_t ta_number,
08963 rsbac_list_handle_t handle, void *desc)
08964 {
08965 struct rsbac_list_lol_reg_item_t *list;
08966 struct rsbac_list_lol_item_t *sublist;
08967 u_long lock_flags, rlock_flags;
08968 long result;
08969 #ifdef CONFIG_RSBAC_LIST_TRANS
08970 u_int hash = 0;
08971 #endif
08972
08973 if (!handle)
08974 return -RSBAC_EINVALIDLIST;
08975 if (!list_initialized)
08976 return -RSBAC_ENOTINITIALIZED;
08977
08978 list = (struct rsbac_list_lol_reg_item_t *) handle;
08979 if (list->self != list)
08980 return -RSBAC_EINVALIDLIST;
08981
08982 #ifdef CONFIG_RSBAC_LIST_TRANS
08983 if (ta_number) {
08984 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08985 return -RSBAC_EINVALIDTRANSACTION;
08986 if(list->hash_function)
08987 hash = list->hash_function(desc, list->nr_hashes);
08988 }
08989 #endif
08990
08991 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08992
08993
08994
08995 rsbac_read_lock(&list->lock, &lock_flags);
08996
08997 #ifdef CONFIG_RSBAC_LIST_TRANS
08998 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
08999 sublist = ta_lookup_lol_item(ta_number, list, desc);
09000 else
09001 #endif
09002 sublist = lookup_lol_item(list, desc);
09003 if (sublist) {
09004 result = sublist->count;
09005 } else {
09006 result = -RSBAC_ENOTFOUND;
09007 }
09008 rsbac_read_unlock(&list->lock, &lock_flags);
09009 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09010 return result;
09011 }
09012
09013 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09014 EXPORT_SYMBOL(rsbac_ta_list_lol_all_subcount);
09015 #endif
09016 long rsbac_ta_list_lol_all_subcount(rsbac_list_ta_number_t ta_number,
09017 rsbac_list_handle_t handle)
09018 {
09019 struct rsbac_list_lol_reg_item_t *list;
09020 struct rsbac_list_lol_item_t *sublist;
09021 u_long lock_flags, rlock_flags;
09022 long result = 0;
09023 int i;
09024
09025 if (!handle)
09026 return -RSBAC_EINVALIDLIST;
09027 if (!list_initialized)
09028 return -RSBAC_ENOTINITIALIZED;
09029
09030 list = (struct rsbac_list_lol_reg_item_t *) handle;
09031 if (list->self != list)
09032 return -RSBAC_EINVALIDLIST;
09033
09034 #ifdef CONFIG_RSBAC_LIST_TRANS
09035 if (ta_number) {
09036 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09037 return -RSBAC_EINVALIDTRANSACTION;
09038 }
09039 #endif
09040
09041 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09042
09043
09044
09045 rsbac_read_lock(&list->lock, &lock_flags);
09046
09047 for (i=0; i<list->nr_hashes; i++) {
09048 #ifdef CONFIG_RSBAC_LIST_TRANS
09049 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09050 sublist = list->hashed[i].ta_head;
09051 else
09052 #endif
09053 sublist = list->hashed[i].head;
09054 while (sublist) {
09055 result += sublist->count;
09056 sublist = sublist->next;
09057 }
09058 }
09059 rsbac_read_unlock(&list->lock, &lock_flags);
09060 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09061 return result;
09062 }
09063
09064 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09065 EXPORT_SYMBOL(rsbac_ta_list_lol_count);
09066 #endif
09067 long rsbac_ta_list_lol_count(rsbac_list_ta_number_t ta_number,
09068 rsbac_list_handle_t handle)
09069 {
09070 struct rsbac_list_lol_reg_item_t *list;
09071 long result = 0;
09072 int i;
09073
09074 if (!handle)
09075 return -RSBAC_EINVALIDLIST;
09076 if (!list_initialized)
09077 return -RSBAC_ENOTINITIALIZED;
09078
09079 list = (struct rsbac_list_lol_reg_item_t *) handle;
09080 if (list->self != list)
09081 return -RSBAC_EINVALIDLIST;
09082
09083 #ifdef CONFIG_RSBAC_LIST_TRANS
09084 if (ta_number) {
09085 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09086 return -RSBAC_EINVALIDTRANSACTION;
09087 }
09088 #endif
09089
09090
09091
09092
09093 for (i=0; i<list->nr_hashes; i++) {
09094 #ifdef CONFIG_RSBAC_LIST_TRANS
09095 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09096 result += list->hashed[i].ta_count;
09097 else
09098 #endif
09099 result += list->hashed[i].count;
09100 }
09101 return result;
09102 }
09103
09104 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09105 EXPORT_SYMBOL(rsbac_ta_list_count);
09106 #endif
09107 long rsbac_ta_list_count(rsbac_list_ta_number_t ta_number,
09108 rsbac_list_handle_t handle)
09109 {
09110 struct rsbac_list_reg_item_t *list;
09111 long result = 0;
09112 int i;
09113
09114 if (!handle)
09115 return -RSBAC_EINVALIDLIST;
09116 if (!list_initialized)
09117 return -RSBAC_ENOTINITIALIZED;
09118
09119 list = (struct rsbac_list_reg_item_t *) handle;
09120 if (list->self != list)
09121 return -RSBAC_EINVALIDLIST;
09122
09123 #ifdef CONFIG_RSBAC_LIST_TRANS
09124 if (ta_number) {
09125 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09126 return -RSBAC_EINVALIDTRANSACTION;
09127 }
09128 #endif
09129
09130 for (i=0; i<list->nr_hashes; i++) {
09131 #ifdef CONFIG_RSBAC_LIST_TRANS
09132 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09133 result += list->hashed[i].ta_count;
09134 else
09135 #endif
09136 result += list->hashed[i].count;
09137 }
09138 return result;
09139 }
09140
09141
09142
09143
09144
09145
09146
09147 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09148 EXPORT_SYMBOL(rsbac_ta_list_get_all_desc);
09149 #endif
09150 long rsbac_ta_list_get_all_desc(rsbac_list_ta_number_t ta_number,
09151 rsbac_list_handle_t handle, void **array_p)
09152 {
09153 struct rsbac_list_reg_item_t *list;
09154 struct rsbac_list_item_t *item_p;
09155 char *buffer;
09156 u_long lock_flags, rlock_flags;
09157 u_long offset = 0;
09158 u_long count = 0;
09159 long result = 0;
09160 u_int item_size;
09161 int i;
09162
09163 if (!handle)
09164 return -RSBAC_EINVALIDLIST;
09165 if (!array_p)
09166 return -RSBAC_EINVALIDPOINTER;
09167 if (!list_initialized)
09168 return -RSBAC_ENOTINITIALIZED;
09169
09170 list = (struct rsbac_list_reg_item_t *) handle;
09171 if (list->self != list)
09172 return -RSBAC_EINVALIDLIST;
09173 *array_p = NULL;
09174
09175 #ifdef CONFIG_RSBAC_LIST_TRANS
09176 if (ta_number) {
09177 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09178 return -RSBAC_EINVALIDTRANSACTION;
09179 }
09180 #endif
09181
09182 rsbac_read_lock(®_head.lock, &rlock_flags);
09183
09184
09185
09186 rsbac_read_lock(&list->lock, &lock_flags);
09187 for (i=0; i<list->nr_hashes; i++) {
09188 #ifdef CONFIG_RSBAC_LIST_TRANS
09189 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09190 count += list->hashed[i].ta_count;
09191 else
09192 #endif
09193 count += list->hashed[i].count;
09194 }
09195 if(!count) {
09196 result = 0;
09197 goto out_unlock;
09198 }
09199 item_size = list->info.desc_size;
09200 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09201 if(count > RSBAC_MAX_KMALLOC / item_size)
09202 count = RSBAC_MAX_KMALLOC / item_size;
09203 #endif
09204 buffer = rsbac_vmalloc(item_size * count);
09205 if (!buffer) {
09206 result = -ENOMEM;
09207 goto out_unlock;
09208 }
09209 for (i=0; i<list->nr_hashes; i++) {
09210 #ifdef CONFIG_RSBAC_LIST_TRANS
09211 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09212 item_p = list->hashed[i].ta_head;
09213 else
09214 #endif
09215 item_p = list->hashed[i].head;
09216 while (item_p && (result < count)) {
09217 if (!item_p->max_age
09218 || (item_p->max_age >
09219 RSBAC_CURRENT_TIME)
09220 ) {
09221 memcpy(buffer + offset,
09222 ((char *) item_p) +
09223 sizeof(*item_p), item_size);
09224 offset += item_size;
09225 result++;
09226 }
09227 item_p = item_p->next;
09228 }
09229 }
09230 *array_p = buffer;
09231
09232 out_unlock:
09233 rsbac_read_unlock(&list->lock, &lock_flags);
09234 rsbac_read_unlock(®_head.lock, &rlock_flags);
09235 return result;
09236 }
09237
09238 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09239 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subdesc_ttl);
09240 #endif
09241 long rsbac_ta_list_lol_get_all_subdesc_ttl(rsbac_list_ta_number_t
09242 ta_number,
09243 rsbac_list_handle_t handle,
09244 void *desc, void **array_p,
09245 rsbac_time_t ** ttl_array_p)
09246 {
09247 struct rsbac_list_lol_reg_item_t *list;
09248 struct rsbac_list_lol_item_t *sublist;
09249 struct rsbac_list_item_t *item_p;
09250 char *buffer;
09251 rsbac_time_t *ttl_p = NULL;
09252 u_long lock_flags, rlock_flags;
09253 u_long offset = 0;
09254 long result = 0;
09255 u_long count;
09256 u_int item_size;
09257 #ifdef CONFIG_RSBAC_LIST_TRANS
09258 u_int hash = 0;
09259 #endif
09260
09261 if (!handle)
09262 return -RSBAC_EINVALIDLIST;
09263 if (!array_p)
09264 return -RSBAC_EINVALIDPOINTER;
09265 if (!list_initialized)
09266 return -RSBAC_ENOTINITIALIZED;
09267
09268 list = (struct rsbac_list_lol_reg_item_t *) handle;
09269 if (list->self != list)
09270 return -RSBAC_EINVALIDLIST;
09271 *array_p = NULL;
09272
09273 #ifdef CONFIG_RSBAC_LIST_TRANS
09274 if (ta_number) {
09275 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09276 return -RSBAC_EINVALIDTRANSACTION;
09277 if(list->hash_function)
09278 hash = list->hash_function(desc, list->nr_hashes);
09279 }
09280 #endif
09281
09282 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09283
09284
09285
09286 rsbac_read_lock(&list->lock, &lock_flags);
09287 #ifdef CONFIG_RSBAC_LIST_TRANS
09288 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
09289 sublist = ta_lookup_lol_item(ta_number, list, desc);
09290 else
09291 #endif
09292 sublist = lookup_lol_item(list, desc);
09293 if (sublist && sublist->count) {
09294 item_size = list->info.subdesc_size;
09295 count = sublist->count;
09296 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09297 if(count > RSBAC_MAX_KMALLOC / item_size)
09298 count = RSBAC_MAX_KMALLOC / item_size;
09299 #endif
09300 buffer = rsbac_vmalloc(item_size * count);
09301 if (buffer) {
09302 if (ttl_array_p)
09303 ttl_p =
09304 rsbac_vmalloc(sizeof(**ttl_array_p) *
09305 sublist->count);
09306 item_p = sublist->head;
09307 while (item_p && (result < count)) {
09308 if (!item_p->max_age
09309 || (item_p->max_age >
09310 RSBAC_CURRENT_TIME)
09311 ) {
09312 memcpy(buffer + offset,
09313 ((char *) item_p) +
09314 sizeof(*item_p), item_size);
09315 if (ttl_p) {
09316 if (item_p->max_age)
09317 ttl_p[result] =
09318 item_p->
09319 max_age -
09320 RSBAC_CURRENT_TIME;
09321 else
09322 ttl_p[result] = 0;
09323 }
09324 offset += item_size;
09325 result++;
09326 }
09327 item_p = item_p->next;
09328 }
09329 *array_p = buffer;
09330 if (ttl_array_p)
09331 *ttl_array_p = ttl_p;
09332 } else {
09333 result = -RSBAC_ENOMEM;
09334 }
09335 }
09336 rsbac_read_unlock(&list->lock, &lock_flags);
09337 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09338 return result;
09339 }
09340
09341 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09342 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_desc);
09343 #endif
09344 long rsbac_ta_list_lol_get_all_desc(rsbac_list_ta_number_t ta_number,
09345 rsbac_list_handle_t handle,
09346 void **array_p)
09347 {
09348 struct rsbac_list_lol_reg_item_t *list;
09349 struct rsbac_list_lol_item_t *item_p;
09350 char *buffer;
09351 u_long lock_flags, rlock_flags;
09352 u_long offset = 0;
09353 long result = 0;
09354 u_int item_size;
09355 int i;
09356 u_long count = 0;
09357
09358 if (!handle)
09359 return -RSBAC_EINVALIDLIST;
09360 if (!array_p)
09361 return -RSBAC_EINVALIDPOINTER;
09362 if (!list_initialized)
09363 return -RSBAC_ENOTINITIALIZED;
09364
09365 list = (struct rsbac_list_lol_reg_item_t *) handle;
09366 if (list->self != list)
09367 return -RSBAC_EINVALIDLIST;
09368 *array_p = NULL;
09369
09370 #ifdef CONFIG_RSBAC_LIST_TRANS
09371 if (ta_number) {
09372 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09373 return -RSBAC_EINVALIDTRANSACTION;
09374 }
09375 #endif
09376
09377 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09378
09379
09380
09381 rsbac_read_lock(&list->lock, &lock_flags);
09382 for (i=0; i<list->nr_hashes; i++) {
09383 #ifdef CONFIG_RSBAC_LIST_TRANS
09384 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09385 count += list->hashed[i].ta_count;
09386 else
09387 #endif
09388 count += list->hashed[i].count;
09389 }
09390 if(!count) {
09391 result = 0;
09392 goto out_unlock;
09393 }
09394 item_size = list->info.desc_size;
09395 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09396 if(count > RSBAC_MAX_KMALLOC / item_size)
09397 count = RSBAC_MAX_KMALLOC / item_size;
09398 #endif
09399 buffer = rsbac_vmalloc(item_size * count);
09400 if (!buffer) {
09401 result = -ENOMEM;
09402 rsbac_pr_debug(lists, "list %s: could not allocate buffer for %u items of size %u!\n",
09403 list->name, count, item_size);
09404 goto out_unlock;
09405 }
09406 for (i=0; i<list->nr_hashes; i++) {
09407 #ifdef CONFIG_RSBAC_LIST_TRANS
09408 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09409 item_p = list->hashed[i].ta_head;
09410 else
09411 #endif
09412 item_p = list->hashed[i].head;
09413 while (item_p && (result < count)) {
09414 if (!item_p->max_age
09415 || (item_p->max_age >
09416 RSBAC_CURRENT_TIME)
09417 ) {
09418 memcpy(buffer + offset,
09419 ((char *) item_p) +
09420 sizeof(*item_p), item_size);
09421 offset += item_size;
09422 result++;
09423 }
09424 item_p = item_p->next;
09425 }
09426 }
09427 *array_p = buffer;
09428
09429 out_unlock:
09430 rsbac_read_unlock(&list->lock, &lock_flags);
09431 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09432 return result;
09433 }
09434
09435
09436
09437
09438
09439
09440 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09441 EXPORT_SYMBOL(rsbac_ta_list_get_all_data);
09442 #endif
09443 long rsbac_ta_list_get_all_data(rsbac_list_ta_number_t ta_number,
09444 rsbac_list_handle_t handle, void **array_p)
09445 {
09446 struct rsbac_list_reg_item_t *list;
09447 struct rsbac_list_item_t *item_p;
09448 char *buffer;
09449 u_long lock_flags, rlock_flags;
09450 u_long offset = 0;
09451 long result = 0;
09452 u_int item_size;
09453 u_int item_offset;
09454 int i;
09455 u_long count = 0;
09456
09457 if (!handle)
09458 return -RSBAC_EINVALIDLIST;
09459 if (!array_p)
09460 return -RSBAC_EINVALIDPOINTER;
09461 if (!list_initialized)
09462 return -RSBAC_ENOTINITIALIZED;
09463
09464 list = (struct rsbac_list_reg_item_t *) handle;
09465 if (list->self != list)
09466 return -RSBAC_EINVALIDLIST;
09467 *array_p = NULL;
09468
09469 #ifdef CONFIG_RSBAC_LIST_TRANS
09470 if (ta_number) {
09471 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09472 return -RSBAC_EINVALIDTRANSACTION;
09473 }
09474 #endif
09475
09476 rsbac_read_lock(®_head.lock, &rlock_flags);
09477
09478
09479
09480 rsbac_read_lock(&list->lock, &lock_flags);
09481 if (!list->info.data_size) {
09482 rsbac_read_unlock(&list->lock, &lock_flags);
09483 rsbac_read_unlock(®_head.lock, &rlock_flags);
09484 return -RSBAC_EINVALIDREQUEST;
09485 }
09486 for (i=0; i<list->nr_hashes; i++) {
09487 #ifdef CONFIG_RSBAC_LIST_TRANS
09488 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09489 count += list->hashed[i].ta_count;
09490 else
09491 #endif
09492 count += list->hashed[i].count;
09493 }
09494 if(!count) {
09495 result = 0;
09496 goto out_unlock;
09497 }
09498 item_size = list->info.data_size;
09499 item_offset = list->info.desc_size;
09500 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09501 if(count > RSBAC_MAX_KMALLOC / item_size)
09502 count = RSBAC_MAX_KMALLOC / item_size;
09503 #endif
09504 buffer = rsbac_vmalloc(item_size * count);
09505 if (!buffer) {
09506 result = -ENOMEM;
09507 goto out_unlock;
09508 }
09509 for (i=0; i<list->nr_hashes; i++) {
09510 #ifdef CONFIG_RSBAC_LIST_TRANS
09511 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09512 item_p = list->hashed[i].ta_head;
09513 else
09514 #endif
09515 item_p = list->hashed[i].head;
09516 while (item_p && (result < count)) {
09517 if (!item_p->max_age
09518 || (item_p->max_age >
09519 RSBAC_CURRENT_TIME)
09520 ) {
09521 memcpy(buffer + offset,
09522 ((char *) item_p) +
09523 sizeof(*item_p) +
09524 item_offset, item_size);
09525 offset += item_size;
09526 result++;
09527 }
09528 item_p = item_p->next;
09529 }
09530 }
09531 *array_p = buffer;
09532
09533 out_unlock:
09534 rsbac_read_unlock(&list->lock, &lock_flags);
09535 rsbac_read_unlock(®_head.lock, &rlock_flags);
09536 return result;
09537 }
09538
09539 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09540 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subdata);
09541 #endif
09542 long rsbac_ta_list_lol_get_all_subdata(rsbac_list_ta_number_t ta_number,
09543 rsbac_list_handle_t handle,
09544 void *desc, void **array_p)
09545 {
09546 struct rsbac_list_lol_reg_item_t *list;
09547 struct rsbac_list_lol_item_t *sublist;
09548 struct rsbac_list_item_t *item_p;
09549 char *buffer;
09550 u_long lock_flags, rlock_flags;
09551 u_long offset = 0;
09552 long result = 0;
09553 u_long count;
09554 u_int item_size;
09555 u_int item_offset;
09556 #ifdef CONFIG_RSBAC_LIST_TRANS
09557 u_int hash = 0;
09558 #endif
09559
09560 if (!handle)
09561 return -RSBAC_EINVALIDLIST;
09562 if (!array_p)
09563 return -RSBAC_EINVALIDPOINTER;
09564 if (!list_initialized)
09565 return -RSBAC_ENOTINITIALIZED;
09566
09567 list = (struct rsbac_list_lol_reg_item_t *) handle;
09568 if (list->self != list)
09569 return -RSBAC_EINVALIDLIST;
09570 *array_p = NULL;
09571
09572 #ifdef CONFIG_RSBAC_LIST_TRANS
09573 if (ta_number) {
09574 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09575 return -RSBAC_EINVALIDTRANSACTION;
09576 if(list->hash_function)
09577 hash = list->hash_function(desc, list->nr_hashes);
09578 }
09579 #endif
09580
09581 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09582
09583
09584
09585 rsbac_read_lock(&list->lock, &lock_flags);
09586 if (!list->info.subdata_size) {
09587 rsbac_read_unlock(&list->lock, &lock_flags);
09588 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09589 return -RSBAC_EINVALIDREQUEST;
09590 }
09591 #ifdef CONFIG_RSBAC_LIST_TRANS
09592 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
09593 sublist = ta_lookup_lol_item(ta_number, list, desc);
09594 else
09595 #endif
09596 sublist = lookup_lol_item(list, desc);
09597 if (sublist && sublist->count) {
09598 item_size = list->info.subdata_size;
09599 item_offset = list->info.subdesc_size;
09600 count = sublist->count;
09601 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09602 if(count > RSBAC_MAX_KMALLOC / item_size)
09603 count = RSBAC_MAX_KMALLOC / item_size;
09604 #endif
09605 buffer = rsbac_vmalloc(item_size * count);
09606 if (buffer) {
09607 item_p = sublist->head;
09608 while (item_p && (result < count)) {
09609 if (!item_p->max_age
09610 || (item_p->max_age >
09611 RSBAC_CURRENT_TIME)
09612 ) {
09613 memcpy(buffer + offset,
09614 ((char *) item_p) +
09615 sizeof(*item_p) +
09616 item_offset, item_size);
09617 offset += item_size;
09618 result++;
09619 }
09620 item_p = item_p->next;
09621 }
09622 *array_p = buffer;
09623 } else {
09624 result = -RSBAC_ENOMEM;
09625 }
09626 }
09627 rsbac_read_unlock(&list->lock, &lock_flags);
09628 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09629 return result;
09630 }
09631
09632 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09633 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_data);
09634 #endif
09635 long rsbac_ta_list_lol_get_all_data(rsbac_list_ta_number_t ta_number,
09636 rsbac_list_handle_t handle,
09637 void **array_p)
09638 {
09639 struct rsbac_list_lol_reg_item_t *list;
09640 struct rsbac_list_lol_item_t *item_p;
09641 char *buffer;
09642 u_long lock_flags, rlock_flags;
09643 u_long offset = 0;
09644 long result = 0;
09645 u_int item_size;
09646 u_int item_offset;
09647 int i;
09648 u_long count = 0;
09649
09650 if (!handle)
09651 return -RSBAC_EINVALIDLIST;
09652 if (!array_p)
09653 return -RSBAC_EINVALIDPOINTER;
09654 if (!list_initialized)
09655 return -RSBAC_ENOTINITIALIZED;
09656
09657 list = (struct rsbac_list_lol_reg_item_t *) handle;
09658 if (list->self != list)
09659 return -RSBAC_EINVALIDLIST;
09660 *array_p = NULL;
09661
09662 #ifdef CONFIG_RSBAC_LIST_TRANS
09663 if (ta_number) {
09664 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09665 return -RSBAC_EINVALIDTRANSACTION;
09666 }
09667 #endif
09668
09669 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09670
09671
09672
09673 rsbac_read_lock(&list->lock, &lock_flags);
09674 if (!list->info.data_size) {
09675 rsbac_read_unlock(&list->lock, &lock_flags);
09676 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09677 return -RSBAC_EINVALIDREQUEST;
09678 }
09679 for (i=0; i<list->nr_hashes; i++) {
09680 #ifdef CONFIG_RSBAC_LIST_TRANS
09681 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09682 count += list->hashed[i].ta_count;
09683 else
09684 #endif
09685 count += list->hashed[i].count;
09686 }
09687 if(!count) {
09688 result = 0;
09689 goto out_unlock;
09690 }
09691 item_size = list->info.data_size;
09692 item_offset = list->info.desc_size;
09693 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09694 if(count > RSBAC_MAX_KMALLOC / item_size)
09695 count = RSBAC_MAX_KMALLOC / item_size;
09696 #endif
09697 buffer = rsbac_vmalloc(item_size * count);
09698 if (!buffer) {
09699 result = -ENOMEM;
09700 goto out_unlock;
09701 }
09702 for (i=0; i<list->nr_hashes; i++) {
09703 #ifdef CONFIG_RSBAC_LIST_TRANS
09704 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09705 item_p = list->hashed[i].ta_head;
09706 else
09707 #endif
09708 item_p = list->hashed[i].head;
09709 while (item_p && (result < count)) {
09710 if (!item_p->max_age
09711 || (item_p->max_age >
09712 RSBAC_CURRENT_TIME)
09713 ) {
09714 memcpy(buffer + offset,
09715 ((char *) item_p) +
09716 sizeof(*item_p) +
09717 item_offset, item_size);
09718 offset += item_size;
09719 result++;
09720 }
09721 item_p = item_p->next;
09722 }
09723 }
09724 *array_p = buffer;
09725
09726 out_unlock:
09727 rsbac_read_unlock(&list->lock, &lock_flags);
09728 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09729 return result;
09730 }
09731
09732
09733
09734 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09735 EXPORT_SYMBOL(rsbac_list_get_item_size);
09736 #endif
09737 int rsbac_list_get_item_size(rsbac_list_handle_t handle)
09738 {
09739 struct rsbac_list_reg_item_t *list;
09740
09741 if (!handle)
09742 return -RSBAC_EINVALIDLIST;
09743 if (!list_initialized)
09744 return -RSBAC_ENOTINITIALIZED;
09745
09746 list = (struct rsbac_list_reg_item_t *) handle;
09747 if (list->self != list)
09748 return -RSBAC_EINVALIDLIST;
09749 return list->info.desc_size + list->info.data_size;
09750 }
09751
09752 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09753 EXPORT_SYMBOL(rsbac_list_lol_get_subitem_size);
09754 #endif
09755 int rsbac_list_lol_get_subitem_size(rsbac_list_handle_t handle)
09756 {
09757 struct rsbac_list_lol_reg_item_t *list;
09758
09759 if (!handle)
09760 return -RSBAC_EINVALIDLIST;
09761 if (!list_initialized)
09762 return -RSBAC_ENOTINITIALIZED;
09763
09764 list = (struct rsbac_list_lol_reg_item_t *) handle;
09765 if (list->self != list)
09766 return -RSBAC_EINVALIDLIST;
09767 return list->info.subdesc_size + list->info.subdata_size;
09768 }
09769
09770 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09771 EXPORT_SYMBOL(rsbac_list_lol_get_item_size);
09772 #endif
09773 int rsbac_list_lol_get_item_size(rsbac_list_handle_t handle)
09774 {
09775 struct rsbac_list_lol_reg_item_t *list;
09776
09777 if (!handle)
09778 return -RSBAC_EINVALIDLIST;
09779 if (!list_initialized)
09780 return -RSBAC_ENOTINITIALIZED;
09781
09782 list = (struct rsbac_list_lol_reg_item_t *) handle;
09783 if (list->self != list)
09784 return -RSBAC_EINVALIDLIST;
09785 return list->info.desc_size + list->info.data_size;
09786 }
09787
09788
09789
09790
09791
09792
09793
09794 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09795 EXPORT_SYMBOL(rsbac_ta_list_get_all_items_ttl);
09796 #endif
09797 long rsbac_ta_list_get_all_items_ttl(rsbac_list_ta_number_t ta_number,
09798 rsbac_list_handle_t handle,
09799 void **array_p,
09800 rsbac_time_t ** ttl_array_p)
09801 {
09802 struct rsbac_list_reg_item_t *list;
09803 struct rsbac_list_item_t *item_p;
09804 char *buffer;
09805 rsbac_time_t *ttl_p = NULL;
09806 u_long lock_flags, rlock_flags;
09807 u_long offset = 0;
09808 long result = 0;
09809 u_int item_size;
09810 int i;
09811 u_long count = 0;
09812
09813 if (!handle)
09814 return -RSBAC_EINVALIDLIST;
09815 if (!array_p)
09816 return -RSBAC_EINVALIDPOINTER;
09817 if (!list_initialized)
09818 return -RSBAC_ENOTINITIALIZED;
09819
09820 list = (struct rsbac_list_reg_item_t *) handle;
09821 if (list->self != list)
09822 return -RSBAC_EINVALIDLIST;
09823 *array_p = NULL;
09824
09825 #ifdef CONFIG_RSBAC_LIST_TRANS
09826 if (ta_number) {
09827 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09828 return -RSBAC_EINVALIDTRANSACTION;
09829 }
09830 #endif
09831
09832 rsbac_read_lock(®_head.lock, &rlock_flags);
09833
09834
09835
09836 rsbac_read_lock(&list->lock, &lock_flags);
09837 for (i=0; i<list->nr_hashes; i++) {
09838 #ifdef CONFIG_RSBAC_LIST_TRANS
09839 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09840 count += list->hashed[i].ta_count;
09841 else
09842 #endif
09843 count += list->hashed[i].count;
09844 }
09845 if(!count) {
09846 result = 0;
09847 goto out_unlock;
09848 }
09849 item_size = list->info.desc_size + list->info.data_size;
09850 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09851 if(count > RSBAC_MAX_KMALLOC / item_size)
09852 count = RSBAC_MAX_KMALLOC / item_size;
09853 #endif
09854 buffer = rsbac_vmalloc(item_size * count);
09855 if (!buffer) {
09856 result = -ENOMEM;
09857 goto out_unlock;
09858 }
09859 if (ttl_array_p) {
09860 ttl_p = rsbac_vmalloc(sizeof(**ttl_array_p) * count);
09861 if (!ttl_p) {
09862 result = -ENOMEM;
09863 rsbac_vfree(buffer);
09864 goto out_unlock;
09865 }
09866 }
09867 for (i=0; i<list->nr_hashes; i++) {
09868 #ifdef CONFIG_RSBAC_LIST_TRANS
09869 if (ta_number && (list->hashed[i].ta_copied == ta_number))
09870 item_p = list->hashed[i].ta_head;
09871 else
09872 #endif
09873 item_p = list->hashed[i].head;
09874 while (item_p && (result < count)) {
09875 if (!item_p->max_age
09876 || (item_p->max_age >
09877 RSBAC_CURRENT_TIME)
09878 ) {
09879 memcpy(buffer + offset,
09880 ((char *) item_p) +
09881 sizeof(*item_p), item_size);
09882 if (ttl_p) {
09883 if (item_p->max_age)
09884 ttl_p[result] =
09885 item_p->max_age - RSBAC_CURRENT_TIME;
09886 else
09887 ttl_p[result] = 0;
09888 }
09889 offset += item_size;
09890 result++;
09891 }
09892 item_p = item_p->next;
09893 }
09894 }
09895 *array_p = buffer;
09896 if (ttl_array_p)
09897 *ttl_array_p = ttl_p;
09898
09899 out_unlock:
09900 rsbac_read_unlock(&list->lock, &lock_flags);
09901 rsbac_read_unlock(®_head.lock, &rlock_flags);
09902 return result;
09903 }
09904
09905 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09906 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subitems_ttl);
09907 #endif
09908 long rsbac_ta_list_lol_get_all_subitems_ttl(rsbac_list_ta_number_t
09909 ta_number,
09910 rsbac_list_handle_t handle,
09911 void *desc, void **array_p,
09912 rsbac_time_t ** ttl_array_p)
09913 {
09914 struct rsbac_list_lol_reg_item_t *list;
09915 struct rsbac_list_lol_item_t *sublist;
09916 struct rsbac_list_item_t *item_p;
09917 char *buffer;
09918 rsbac_time_t *ttl_p = NULL;
09919 u_long lock_flags, rlock_flags;
09920 u_long offset = 0;
09921 long result = 0;
09922 u_long count;
09923 u_int item_size;
09924 #ifdef CONFIG_RSBAC_LIST_TRANS
09925 u_int hash = 0;
09926 #endif
09927
09928 if (!handle)
09929 return -RSBAC_EINVALIDLIST;
09930 if (!array_p)
09931 return -RSBAC_EINVALIDPOINTER;
09932 if (!list_initialized)
09933 return -RSBAC_ENOTINITIALIZED;
09934
09935 list = (struct rsbac_list_lol_reg_item_t *) handle;
09936 if (list->self != list)
09937 return -RSBAC_EINVALIDLIST;
09938 *array_p = NULL;
09939
09940 #ifdef CONFIG_RSBAC_LIST_TRANS
09941 if (ta_number) {
09942 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09943 return -RSBAC_EINVALIDTRANSACTION;
09944 if(list->hash_function)
09945 hash = list->hash_function(desc, list->nr_hashes);
09946 }
09947 #endif
09948
09949 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09950
09951
09952
09953 rsbac_read_lock(&list->lock, &lock_flags);
09954 #ifdef CONFIG_RSBAC_LIST_TRANS
09955 if (ta_number && (list->hashed[hash].ta_copied == ta_number))
09956 sublist = ta_lookup_lol_item(ta_number, list, desc);
09957 else
09958 #endif
09959 sublist = lookup_lol_item(list, desc);
09960 if (sublist && sublist->count) {
09961 count = sublist->count;
09962 item_size =
09963 list->info.subdesc_size + list->info.subdata_size;
09964 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
09965 if(count > RSBAC_MAX_KMALLOC / item_size)
09966 count = RSBAC_MAX_KMALLOC / item_size;
09967 #endif
09968 buffer = rsbac_vmalloc(item_size * count);
09969 if (buffer) {
09970 if (ttl_array_p)
09971 ttl_p =
09972 rsbac_vmalloc(sizeof(**ttl_array_p) *
09973 sublist->count);
09974 item_p = sublist->head;
09975 while (item_p && (result < count)) {
09976 if (!item_p->max_age
09977 || (item_p->max_age >
09978 RSBAC_CURRENT_TIME)
09979 ) {
09980 memcpy(buffer + offset,
09981 ((char *) item_p) +
09982 sizeof(*item_p), item_size);
09983 if (ttl_p) {
09984 if (item_p->max_age)
09985 ttl_p[result] =
09986 item_p->
09987 max_age -
09988 RSBAC_CURRENT_TIME;
09989 else
09990 ttl_p[result] = 0;
09991 }
09992 offset += item_size;
09993 result++;
09994 }
09995 item_p = item_p->next;
09996 }
09997 *array_p = buffer;
09998 if (ttl_array_p)
09999 *ttl_array_p = ttl_p;
10000 } else {
10001 result = -RSBAC_ENOMEM;
10002 }
10003 }
10004 rsbac_read_unlock(&list->lock, &lock_flags);
10005 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10006 return result;
10007 }
10008
10009 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10010 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_items);
10011 #endif
10012 long rsbac_ta_list_lol_get_all_items(rsbac_list_ta_number_t ta_number,
10013 rsbac_list_handle_t handle,
10014 void **array_p)
10015 {
10016 struct rsbac_list_lol_reg_item_t *list;
10017 struct rsbac_list_lol_item_t *item_p;
10018 char *buffer;
10019 u_long lock_flags, rlock_flags;
10020 u_long offset = 0;
10021 long result = 0;
10022 u_int item_size;
10023 int i;
10024 u_long count = 0;
10025
10026 if (!handle)
10027 return -RSBAC_EINVALIDLIST;
10028 if (!array_p)
10029 return -RSBAC_EINVALIDPOINTER;
10030 if (!list_initialized)
10031 return -RSBAC_ENOTINITIALIZED;
10032
10033 list = (struct rsbac_list_lol_reg_item_t *) handle;
10034 if (list->self != list)
10035 return -RSBAC_EINVALIDLIST;
10036 *array_p = NULL;
10037
10038 #ifdef CONFIG_RSBAC_LIST_TRANS
10039 if (ta_number) {
10040 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10041 return -RSBAC_EINVALIDTRANSACTION;
10042 }
10043 #endif
10044
10045 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10046
10047
10048
10049 rsbac_read_lock(&list->lock, &lock_flags);
10050 for (i=0; i<list->nr_hashes; i++) {
10051 #ifdef CONFIG_RSBAC_LIST_TRANS
10052 if (ta_number && (list->hashed[i].ta_copied == ta_number))
10053 count += list->hashed[i].ta_count;
10054 else
10055 #endif
10056 count += list->hashed[i].count;
10057 }
10058 if(!count) {
10059 result = 0;
10060 goto out_unlock;
10061 }
10062 item_size = list->info.desc_size + list->info.data_size;
10063 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
10064 if(count > RSBAC_MAX_KMALLOC / item_size)
10065 count = RSBAC_MAX_KMALLOC / item_size;
10066 #endif
10067 buffer = rsbac_vmalloc(item_size * count);
10068 if (!buffer) {
10069 result = -ENOMEM;
10070 goto out_unlock;
10071 }
10072 for (i=0; i<list->nr_hashes; i++) {
10073 #ifdef CONFIG_RSBAC_LIST_TRANS
10074 if (ta_number && (list->hashed[i].ta_copied == ta_number))
10075 item_p = list->hashed[i].ta_head;
10076 else
10077 #endif
10078 item_p = list->hashed[i].head;
10079 while (item_p && (result < count)) {
10080 if (!item_p->max_age
10081 || (item_p->max_age >
10082 RSBAC_CURRENT_TIME)
10083 ) {
10084 memcpy(buffer + offset,
10085 ((char *) item_p) +
10086 sizeof(*item_p), item_size);
10087 offset += item_size;
10088 result++;
10089 }
10090 item_p = item_p->next;
10091 }
10092 }
10093 *array_p = buffer;
10094
10095 out_unlock:
10096 rsbac_read_unlock(&list->lock, &lock_flags);
10097 rsbac_read_unlock(®_head.lock, &rlock_flags);
10098 return result;
10099 }
10100
10101
10102
10103
10104
10105
10106
10107 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10108 EXPORT_SYMBOL(rsbac_list_hash_u32);
10109 #endif
10110 u_int rsbac_list_hash_u32(void * desc, __u32 nr_hashes)
10111 {
10112 return (*((__u32 *) desc) & (nr_hashes - 1));
10113 }
10114
10115 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10116 EXPORT_SYMBOL(rsbac_list_hash_fd);
10117 #endif
10118 u_int rsbac_list_hash_fd(void * desc, __u32 nr_hashes)
10119 {
10120 return (*((rsbac_inode_nr_t *) desc) & (nr_hashes - 1));
10121 }
10122
10123 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10124 EXPORT_SYMBOL(rsbac_list_hash_pid);
10125 #endif
10126 u_int rsbac_list_hash_pid(void * desc, __u32 nr_hashes)
10127 {
10128 return (*((rsbac_pid_t *) desc) & (nr_hashes - 1));
10129 }
10130
10131 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10132 EXPORT_SYMBOL(rsbac_list_hash_uid);
10133 #endif
10134 u_int rsbac_list_hash_uid(void * desc, __u32 nr_hashes)
10135 {
10136 return (*((rsbac_uid_t *) desc) & (nr_hashes - 1));
10137 }
10138
10139 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10140 EXPORT_SYMBOL(rsbac_list_hash_gid);
10141 #endif
10142 u_int rsbac_list_hash_gid(void * desc, __u32 nr_hashes)
10143 {
10144 return (*((rsbac_gid_t *) desc) & (nr_hashes - 1));
10145 }
10146
10147 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10148 EXPORT_SYMBOL(rsbac_list_hash_ipc);
10149 #endif
10150 u_int rsbac_list_hash_ipc(void * desc, __u32 nr_hashes)
10151 {
10152 return (((struct rsbac_ipc_t *) desc)->id.id_nr & (nr_hashes - 1));
10153 }
10154
10155 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10156 EXPORT_SYMBOL(rsbac_list_hash_dev);
10157 #endif
10158 u_int rsbac_list_hash_dev(void * desc, __u32 nr_hashes)
10159 {
10160 return ( ( ((struct rsbac_dev_desc_t *) desc)->major
10161 + ((struct rsbac_dev_desc_t *) desc)->minor )
10162 & (nr_hashes - 1));
10163 }
10164
10165 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10166 EXPORT_SYMBOL(rsbac_list_hash_nettemp);
10167 #endif
10168 u_int rsbac_list_hash_nettemp(void * desc, __u32 nr_hashes)
10169 {
10170 return (*((rsbac_net_temp_id_t *) desc) & (nr_hashes - 1));
10171 }
10172
10173 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10174 EXPORT_SYMBOL(rsbac_list_hash_netobj);
10175 #endif
10176 u_int rsbac_list_hash_netobj(void * desc, __u32 nr_hashes)
10177 {
10178 return (*((__u32 *) desc) & (nr_hashes - 1));
10179 }
10180
10181
10182 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10183 EXPORT_SYMBOL(rsbac_list_copy);
10184 #endif
10185 long rsbac_list_copy(rsbac_list_ta_number_t ta_number,
10186 rsbac_list_handle_t from_handle,
10187 rsbac_list_handle_t to_handle)
10188 {
10189 struct rsbac_list_reg_item_t *from_list;
10190 struct rsbac_list_reg_item_t *to_list;
10191 struct rsbac_list_item_t *item_p;
10192 u_long rlock_flags, from_lock_flags, to_lock_flags;
10193 int i;
10194 int err = 0;
10195
10196 if (!from_handle || !to_handle)
10197 return -RSBAC_EINVALIDLIST;
10198
10199 from_list = (struct rsbac_list_reg_item_t *) from_handle;
10200 if (from_list->self != from_list)
10201 return -RSBAC_EINVALIDLIST;
10202 to_list = (struct rsbac_list_reg_item_t *) to_handle;
10203 if (to_list->self != to_list)
10204 return -RSBAC_EINVALIDLIST;
10205 if((from_list->info.desc_size != to_list->info.desc_size)
10206 || (from_list->info.data_size != to_list->info.data_size))
10207 return -RSBAC_EINVALIDVALUE;
10208
10209 #ifdef CONFIG_RSBAC_LIST_TRANS
10210 if (ta_number) {
10211 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10212 return -RSBAC_EINVALIDTRANSACTION;
10213 }
10214 #endif
10215
10216 rsbac_read_lock(®_head.lock, &rlock_flags);
10217 rsbac_pr_debug(lists, "list %s to list %s.\n",
10218 from_list->name, to_list->name);
10219 rsbac_read_lock(&from_list->lock, &from_lock_flags);
10220 rsbac_write_lock(&to_list->lock, &to_lock_flags);
10221
10222 #ifdef CONFIG_RSBAC_LIST_TRANS
10223
10224 if(ta_number)
10225 for (i=0; i<to_list->nr_hashes; i++)
10226 if(to_list->hashed[i].ta_copied != ta_number) {
10227 err = -RSBAC_EBUSY;
10228 goto out_unlock;
10229 }
10230 #endif
10231 for (i=0; i<to_list->nr_hashes; i++) {
10232 #ifdef CONFIG_RSBAC_LIST_TRANS
10233 if(ta_number && (to_list->hashed[i].ta_copied == ta_number))
10234 ta_remove_all_items(to_list, i);
10235 else
10236 #endif
10237 remove_all_items(to_list, i);
10238 }
10239 for (i=0; i<from_list->nr_hashes; i++) {
10240 #ifdef CONFIG_RSBAC_LIST_TRANS
10241 if (ta_number) {
10242 if(from_list->hashed[i].ta_copied == ta_number)
10243 item_p = from_list->hashed[i].ta_head;
10244 else
10245 item_p = from_list->hashed[i].head;
10246 while(item_p) {
10247 if (!ta_add_item(ta_number,
10248 to_list,
10249 item_p->max_age,
10250 &item_p[1],
10251 &item_p[1] + from_list->info.desc_size)) {
10252 err = -RSBAC_EWRITEFAILED;
10253 goto out_unlock;
10254 }
10255 item_p = item_p->next;
10256 }
10257 }
10258 else
10259 #endif
10260 {
10261 item_p = from_list->hashed[i].head;
10262 while(item_p) {
10263 if (!add_item(to_list,
10264 item_p->max_age,
10265 &item_p[1],
10266 &item_p[1] + from_list->info.desc_size)) {
10267 err = -RSBAC_EWRITEFAILED;
10268 goto out_unlock;
10269 }
10270 item_p = item_p->next;
10271 }
10272 }
10273 }
10274
10275 out_unlock:
10276 rsbac_write_unlock(&to_list->lock, &to_lock_flags);
10277 rsbac_read_unlock(&from_list->lock, &from_lock_flags);
10278 rsbac_read_unlock(®_head.lock, &rlock_flags);
10279 return err;
10280 }
10281
10282 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10283 EXPORT_SYMBOL(rsbac_list_lol_copy);
10284 #endif
10285 long rsbac_list_lol_copy(rsbac_list_ta_number_t ta_number,
10286 rsbac_list_handle_t from_handle,
10287 rsbac_list_handle_t to_handle)
10288 {
10289 struct rsbac_list_lol_reg_item_t *from_list;
10290 struct rsbac_list_lol_reg_item_t *to_list;
10291 struct rsbac_list_lol_item_t *item_p;
10292 struct rsbac_list_lol_item_t *new_item_p;
10293 struct rsbac_list_item_t *subitem_p;
10294 struct rsbac_list_item_t *new_subitem_p;
10295 u_long rlock_flags, from_lock_flags, to_lock_flags;
10296 u_int subitem_size;
10297 int i;
10298 int err = 0;
10299
10300 if (!from_handle || !to_handle)
10301 return -RSBAC_EINVALIDLIST;
10302
10303 from_list = (struct rsbac_list_lol_reg_item_t *) from_handle;
10304 if (from_list->self != from_list)
10305 return -RSBAC_EINVALIDLIST;
10306 to_list = (struct rsbac_list_lol_reg_item_t *) to_handle;
10307 if (to_list->self != to_list)
10308 return -RSBAC_EINVALIDLIST;
10309 if((from_list->info.desc_size != to_list->info.desc_size)
10310 || (from_list->info.data_size != to_list->info.data_size)
10311 || (from_list->info.subdesc_size != to_list->info.subdesc_size)
10312 || (from_list->info.subdata_size != to_list->info.subdata_size))
10313 return -RSBAC_EINVALIDVALUE;
10314
10315 #ifdef CONFIG_RSBAC_LIST_TRANS
10316 if (ta_number) {
10317 if (!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10318 return -RSBAC_EINVALIDTRANSACTION;
10319 }
10320 #endif
10321
10322 subitem_size = sizeof(*new_subitem_p)
10323 + from_list->info.subdesc_size + from_list->info.subdata_size;
10324
10325 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10326 rsbac_pr_debug(lists, "list %s to list %s.\n",
10327 from_list->name, to_list->name);
10328 rsbac_read_lock(&from_list->lock, &from_lock_flags);
10329 rsbac_write_lock(&to_list->lock, &to_lock_flags);
10330
10331 #ifdef CONFIG_RSBAC_LIST_TRANS
10332
10333 if(ta_number)
10334 for (i=0; i<to_list->nr_hashes; i++)
10335 if(to_list->hashed[i].ta_copied != ta_number) {
10336 err = -RSBAC_EBUSY;
10337 goto out_unlock;
10338 }
10339 #endif
10340 for (i=0; i<to_list->nr_hashes; i++) {
10341 #ifdef CONFIG_RSBAC_LIST_TRANS
10342 if(ta_number && (to_list->hashed[i].ta_copied == ta_number))
10343 ta_remove_all_lol_items(to_list, i);
10344 else
10345 #endif
10346 remove_all_lol_items(to_list, i);
10347 }
10348 for (i=0; i<from_list->nr_hashes; i++) {
10349 #ifdef CONFIG_RSBAC_LIST_TRANS
10350 if (ta_number) {
10351 if(from_list->hashed[i].ta_copied == ta_number)
10352 item_p = from_list->hashed[i].ta_head;
10353 else
10354 item_p = from_list->hashed[i].head;
10355 while(item_p) {
10356 new_item_p = ta_add_lol_item(ta_number,
10357 to_list,
10358 item_p->max_age,
10359 &item_p[1],
10360 &item_p[1] + from_list->info.desc_size);
10361 if(!new_item_p) {
10362 err = -RSBAC_EWRITEFAILED;
10363 goto out_unlock;
10364 }
10365 subitem_p = item_p->head;
10366 while (subitem_p) {
10367 if (!(new_subitem_p = rsbac_kmalloc(subitem_size))) {
10368 err = -RSBAC_ENOMEM;
10369 goto out_unlock;
10370 }
10371 memcpy(new_subitem_p, subitem_p, subitem_size);
10372 new_subitem_p->prev = NULL;
10373 new_subitem_p->next = NULL;
10374 if (new_item_p->tail) {
10375 new_subitem_p->prev = new_item_p->tail;
10376 new_item_p->tail->next = new_subitem_p;
10377 new_item_p->tail = new_subitem_p;
10378 new_item_p->count++;
10379 } else {
10380 new_item_p->head = new_subitem_p;
10381 new_item_p->tail = new_subitem_p;
10382 new_item_p->count = 1;
10383 }
10384 subitem_p = subitem_p->next;
10385 }
10386 item_p = item_p->next;
10387 }
10388 }
10389 else
10390 #endif
10391 {
10392 item_p = from_list->hashed[i].head;
10393 while(item_p) {
10394 new_item_p = add_lol_item(to_list,
10395 item_p->max_age,
10396 &item_p[1],
10397 &item_p[1] + from_list->info.desc_size);
10398 if(!new_item_p) {
10399 err = -RSBAC_EWRITEFAILED;
10400 goto out_unlock;
10401 }
10402 subitem_p = item_p->head;
10403 while (subitem_p) {
10404 if (!(new_subitem_p = rsbac_kmalloc(subitem_size))) {
10405 err = -RSBAC_ENOMEM;
10406 goto out_unlock;
10407 }
10408 memcpy(new_subitem_p, subitem_p, subitem_size);
10409 new_subitem_p->prev = NULL;
10410 new_subitem_p->next = NULL;
10411 if (new_item_p->tail) {
10412 new_subitem_p->prev = new_item_p->tail;
10413 new_item_p->tail->next = new_subitem_p;
10414 new_item_p->tail = new_subitem_p;
10415 new_item_p->count++;
10416 } else {
10417 new_item_p->head = new_subitem_p;
10418 new_item_p->tail = new_subitem_p;
10419 new_item_p->count = 1;
10420 }
10421 subitem_p = subitem_p->next;
10422 }
10423 item_p = item_p->next;
10424 }
10425 }
10426 }
10427
10428 out_unlock:
10429 rsbac_write_unlock(&to_list->lock, &to_lock_flags);
10430 rsbac_read_unlock(&from_list->lock, &from_lock_flags);
10431 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10432 return err;
10433 }
10434
10435 static int do_rehash(struct rsbac_list_reg_item_t *list, u_int new_nr)
10436 {
10437 struct rsbac_list_hashed_t * old_hashed;
10438 int i;
10439 struct rsbac_list_item_t *item_p;
10440 struct rsbac_list_item_t *next_item_p;
10441 u_int new_hash;
10442 u_int old_nr;
10443
10444 #ifdef CONFIG_RSBAC_LIST_TRANS
10445 for(i=0; i<list->nr_hashes; i++)
10446 if(list->hashed[i].ta_copied)
10447 return -RSBAC_EBUSY;
10448 #endif
10449 old_hashed = list->hashed;
10450 list->hashed = rsbac_kmalloc(new_nr*sizeof(struct rsbac_list_hashed_t));
10451 if(!list->hashed) {
10452 list->hashed = old_hashed;
10453 return -RSBAC_ENOMEM;
10454 }
10455 memset(list->hashed, 0, new_nr*sizeof(struct rsbac_list_hashed_t));
10456 old_nr = list->nr_hashes;
10457 list->nr_hashes = new_nr;
10458 for(i=0; i<old_nr; i++) {
10459 item_p = old_hashed[i].head;
10460 while(item_p) {
10461 next_item_p = item_p->next;
10462 new_hash = list->hash_function(&item_p[1], new_nr);
10463 if (!list->hashed[new_hash].head) {
10464 list->hashed[new_hash].head = item_p;
10465 list->hashed[new_hash].tail = item_p;
10466 list->hashed[new_hash].curr = item_p;
10467 list->hashed[new_hash].count = 1;
10468 item_p->prev = NULL;
10469 item_p->next = NULL;
10470 } else
10471 if (list->compare)
10472 insert_item_compare(list, &item_p[1], item_p);
10473 else
10474 insert_item_memcmp(list, &item_p[1], item_p);
10475 item_p = next_item_p;
10476 }
10477 }
10478 return 0;
10479 }
10480
10481 static int do_lol_rehash(struct rsbac_list_lol_reg_item_t *list, u_int new_nr)
10482 {
10483 struct rsbac_list_lol_hashed_t * old_hashed;
10484 int i;
10485 struct rsbac_list_lol_item_t *item_p;
10486 struct rsbac_list_lol_item_t *next_item_p;
10487 u_int new_hash;
10488 u_int old_nr;
10489
10490 #ifdef CONFIG_RSBAC_LIST_TRANS
10491 for(i=0; i<list->nr_hashes; i++)
10492 if(list->hashed[i].ta_copied)
10493 return -RSBAC_EBUSY;
10494 #endif
10495 old_hashed = list->hashed;
10496 list->hashed = rsbac_kmalloc(new_nr*sizeof(struct rsbac_list_lol_hashed_t));
10497 if(!list->hashed) {
10498 list->hashed = old_hashed;
10499 return -RSBAC_ENOMEM;
10500 }
10501 memset(list->hashed, 0, new_nr*sizeof(struct rsbac_list_lol_hashed_t));
10502 old_nr = list->nr_hashes;
10503 list->nr_hashes = new_nr;
10504 for(i=0; i<old_nr; i++) {
10505 item_p = old_hashed[i].head;
10506 while(item_p) {
10507 next_item_p = item_p->next;
10508 new_hash = list->hash_function(&item_p[1], new_nr);
10509 if (!list->hashed[new_hash].head) {
10510 list->hashed[new_hash].head = item_p;
10511 list->hashed[new_hash].tail = item_p;
10512 list->hashed[new_hash].curr = item_p;
10513 list->hashed[new_hash].count = 1;
10514 item_p->prev = NULL;
10515 item_p->next = NULL;
10516 } else
10517 if (list->compare)
10518 insert_lol_item_compare(list, &item_p[1], item_p);
10519 else
10520 insert_lol_item_memcmp(list, &item_p[1], item_p);
10521 item_p = next_item_p;
10522 }
10523 }
10524 return 0;
10525 }
10526
10527
10528 int rsbac_list_auto_rehash(void)
10529 {
10530 int i;
10531 int err;
10532 struct rsbac_list_reg_item_t *list;
10533 struct rsbac_list_lol_reg_item_t *lol_list;
10534 u_long rlock_flags, lock_flags;
10535 long count;
10536 u_int nr_rehashed = 0;
10537
10538 rsbac_read_lock(®_head.lock, &rlock_flags);
10539 list = reg_head.head;
10540 while(list) {
10541 if((list->flags & RSBAC_LIST_AUTO_HASH_RESIZE)
10542 && (list->nr_hashes < rsbac_list_max_hashes)) {
10543 count = 0;
10544 for (i=0; i<list->nr_hashes; i++) {
10545 count += list->hashed[i].count;
10546 }
10547 if(count / list->nr_hashes > RSBAC_LIST_AUTO_REHASH_TRIGGER) {
10548 u_int new_nr;
10549
10550 new_nr = list->nr_hashes;
10551 while((new_nr < rsbac_list_max_hashes)
10552 && (count / new_nr > RSBAC_LIST_AUTO_REHASH_TRIGGER))
10553 new_nr = new_nr << 1;
10554 if(new_nr > rsbac_list_max_hashes)
10555 new_nr = rsbac_list_max_hashes;
10556 rsbac_printk(KERN_INFO "rsbac_list_auto_rehash(): changing list %s hash size on device %02u:%02u from %u to %u\n",
10557 list->name, MAJOR(list->device), MINOR(list->device), list->nr_hashes, new_nr);
10558 rsbac_write_lock(&list->lock, &lock_flags);
10559 err = do_rehash(list, new_nr);
10560 rsbac_write_unlock(&list->lock, &lock_flags);
10561 if(!err)
10562 nr_rehashed++;
10563 else {
10564 rsbac_printk(KERN_WARNING "rsbac_list_auto_rehash(): changing list %s hash size on device %02u:%02u from %u to %u failed with error %i\n",
10565 list->name, MAJOR(list->device), MINOR(list->device), list->nr_hashes, new_nr, err);
10566 }
10567 }
10568 }
10569 list = list->next;
10570 }
10571 rsbac_read_unlock(®_head.lock, &rlock_flags);
10572 rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10573 lol_list = lol_reg_head.head;
10574 while(lol_list) {
10575 if((lol_list->flags & RSBAC_LIST_AUTO_HASH_RESIZE)
10576 && (lol_list->nr_hashes < rsbac_list_lol_max_hashes)) {
10577 count = 0;
10578 for (i=0; i<lol_list->nr_hashes; i++) {
10579 count += lol_list->hashed[i].count;
10580 }
10581 if(count / lol_list->nr_hashes > RSBAC_LIST_AUTO_REHASH_TRIGGER) {
10582 u_int new_nr;
10583
10584 new_nr = lol_list->nr_hashes;
10585 while((new_nr < rsbac_list_lol_max_hashes)
10586 && (count / new_nr > RSBAC_LIST_AUTO_REHASH_TRIGGER))
10587 new_nr = new_nr << 1;
10588 if(new_nr > rsbac_list_lol_max_hashes)
10589 new_nr = rsbac_list_lol_max_hashes;
10590 rsbac_printk(KERN_INFO "rsbac_list_auto_rehash(): changing list of lists %s hash size on device %02u:%02u from %u to %u\n",
10591 lol_list->name, MAJOR(lol_list->device), MINOR(lol_list->device), lol_list->nr_hashes, new_nr);
10592 rsbac_write_lock(&lol_list->lock, &lock_flags);
10593 err = do_lol_rehash(lol_list, new_nr);
10594 rsbac_write_unlock(&lol_list->lock, &lock_flags);
10595 if(!err)
10596 nr_rehashed++;
10597 else {
10598 rsbac_printk(KERN_WARNING "rsbac_list_auto_rehash(): changing list of lists %s hash size on device %02u:%02u from %u to %u failed with error %i\n",
10599 lol_list->name, MAJOR(lol_list->device), MINOR(lol_list->device), lol_list->nr_hashes, new_nr, err);
10600 }
10601 }
10602 }
10603 lol_list = lol_list->next;
10604 }
10605 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10606
10607 if(nr_rehashed > 0)
10608 rsbac_printk(KERN_INFO "rsbac_list_auto_rehash(): %u lists rehashed\n",
10609 nr_rehashed);
10610 return nr_rehashed;
10611 }
10612
10613 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10614 EXPORT_SYMBOL(rsbac_list_get_nr_hashes);
10615 #endif
10616 long rsbac_list_get_nr_hashes(rsbac_list_handle_t handle)
10617 {
10618 struct rsbac_list_reg_item_t *list;
10619
10620 if (!handle)
10621 return -RSBAC_EINVALIDLIST;
10622 if (!list_initialized)
10623 return -RSBAC_ENOTINITIALIZED;
10624
10625 list = (struct rsbac_list_reg_item_t *) handle;
10626 if (list->self != list)
10627 return -RSBAC_EINVALIDLIST;
10628
10629 return list->nr_hashes;
10630 }
10631
10632 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10633 EXPORT_SYMBOL(rsbac_list_lol_get_nr_hashes);
10634 #endif
10635 long rsbac_list_lol_get_nr_hashes(rsbac_list_handle_t handle)
10636 {
10637 struct rsbac_list_lol_reg_item_t *list;
10638
10639 if (!handle)
10640 return -RSBAC_EINVALIDLIST;
10641 if (!list_initialized)
10642 return -RSBAC_ENOTINITIALIZED;
10643
10644 list = (struct rsbac_list_lol_reg_item_t *) handle;
10645 if (list->self != list)
10646 return -RSBAC_EINVALIDLIST;
10647
10648 return list->nr_hashes;
10649 }