mac_data_structures.c

Go to the documentation of this file.
00001 /*************************************************** */
00002 /* Rule Set Based Access Control                     */
00003 /* Implementation of MAC data structures            */
00004 /* Author and (c) 1999-2005: Amon Ott <ao@rsbac.org> */
00005 /*                                                   */
00006 /* Last modified: 14/Jul/2005                        */
00007 /*************************************************** */
00008 
00009 #include <linux/types.h>
00010 #include <linux/sched.h>
00011 #include <linux/mm.h>
00012 #include <linux/init.h>
00013 #include <linux/ext2_fs.h>
00014 #include <asm/uaccess.h>
00015 #include <rsbac/types.h>
00016 #include <rsbac/aci_data_structures.h>
00017 #include <rsbac/mac_data_structures.h>
00018 #include <rsbac/error.h>
00019 #include <rsbac/helpers.h>
00020 #include <rsbac/adf.h>
00021 #include <rsbac/aci.h>
00022 #include <rsbac/lists.h>
00023 #include <rsbac/proc_fs.h>
00024 #include <rsbac/rkmem.h>
00025 #include <rsbac/getname.h>
00026 #include <linux/string.h>
00027 #include <linux/smp_lock.h>
00028 
00029 /************************************************************************** */
00030 /*                          Global Variables                                */
00031 /************************************************************************** */
00032 
00033 static struct rsbac_mac_device_list_head_t      device_list_head;
00034 
00035 static rsbac_list_handle_t process_handle = NULL;
00036 
00037 /**************************************************/
00038 /*       Declarations of external functions       */
00039 /**************************************************/
00040 
00041 rsbac_boolean_t writable(struct super_block * sb_p);
00042 
00043 /**************************************************/
00044 /*       Declarations of internal functions       */
00045 /**************************************************/
00046 
00047 /************************************************* */
00048 /*               Internal Help functions           */
00049 /************************************************* */
00050 
00051 static inline int fd_hash(rsbac_inode_nr_t inode)
00052   {
00053     return(inode % RSBAC_MAC_NR_TRU_FD_LISTS);
00054   }
00055 
00056 /* mac_register_fd_lists() */
00057 /* register fd ACL lists for device */
00058 
00059 static int mac_register_fd_lists(struct rsbac_mac_device_list_item_t * device_p,
00060                                   kdev_t kdev)
00061   {
00062     char                          * name;
00063     int                             err = 0;
00064     int                             tmperr;
00065     char                            number[10];
00066     u_int                           file_no;
00067     struct rsbac_list_lol_info_t lol_info;
00068 
00069     if(!device_p)
00070       return(-RSBAC_EINVALIDPOINTER);
00071     name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00072     if(!name)
00073       return -RSBAC_ENOMEM;
00074 
00075     /* register all the MAC lists of lists */
00076     for (file_no = 0; file_no < RSBAC_MAC_NR_TRU_FD_LISTS; file_no++)
00077       {
00078         /* construct name from base name + number */
00079         strcpy(name, RSBAC_MAC_FD_FILENAME);
00080         strcat(name, inttostr(number,file_no) );
00081 
00082         lol_info.version = RSBAC_MAC_FD_LIST_VERSION;
00083         lol_info.key = RSBAC_MAC_LIST_KEY;
00084         lol_info.desc_size = sizeof(rsbac_inode_nr_t);
00085         lol_info.data_size = 0;
00086         lol_info.subdesc_size = sizeof(rsbac_uid_t);
00087         lol_info.subdata_size = 0; /* rights */
00088         lol_info.max_age = 0;
00089         tmperr = rsbac_list_lol_register(RSBAC_LIST_VERSION,
00090                                          &(device_p->handles[file_no]),
00091                                          &lol_info,
00092                                          RSBAC_LIST_PERSIST | RSBAC_LIST_DEF_DATA,
00093                                          rsbac_list_compare_u32,
00094                                          rsbac_list_compare_u32,
00095                                          NULL,
00096                                          NULL,
00097                                          NULL,
00098                                          NULL,
00099                                          name,
00100                                          kdev);
00101         if(tmperr)
00102           {
00103             char * tmp;
00104 
00105             tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00106             if(tmp)
00107               {
00108                 rsbac_printk(KERN_WARNING
00109                        "mac_register_fd_lists(): registering list %s for device %02u:%02u failed with error %s!\n",
00110                        name,
00111                        RSBAC_MAJOR(kdev),
00112                        RSBAC_MINOR(kdev),
00113                        get_error_name(tmp, tmperr));
00114                 rsbac_kfree(tmp);
00115               }
00116             err = tmperr;
00117           }
00118       }
00119     return err;
00120   }
00121 
00122 /* mac_detach_fd_lists() */
00123 /* detach from fd MAC lists for device */
00124 
00125 static int mac_detach_fd_lists(struct rsbac_mac_device_list_item_t * device_p)
00126   {
00127     char                          * name;
00128     int                             err = 0;
00129     int                             tmperr;
00130     char                            number[10];
00131     u_int                           file_no;
00132 
00133     if(!device_p)
00134       return(-RSBAC_EINVALIDPOINTER);
00135     name = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00136     if(!name)
00137       return -RSBAC_ENOMEM;
00138 
00139     /* detach all the MAC lists of lists */
00140     for (file_no = 0; file_no < RSBAC_MAC_NR_TRU_FD_LISTS; file_no++)
00141       {
00142         /* construct name from base name + number */
00143         strcpy(name, RSBAC_MAC_FD_FILENAME);
00144         strcat(name, inttostr(number,file_no) );
00145 
00146         tmperr = rsbac_list_lol_detach(&device_p->handles[file_no],
00147                                        RSBAC_MAC_LIST_KEY);
00148         if(tmperr)
00149           {
00150             char * tmp;
00151 
00152             tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00153             if(tmp)
00154               {
00155                 rsbac_printk(KERN_WARNING
00156                        "mac_detach_fd_lists(): detaching from list %s for device %02u:%02u failed with error %s!\n",
00157                        name,
00158                        RSBAC_MAJOR(device_p->id),
00159                        RSBAC_MINOR(device_p->id),
00160                        get_error_name(tmp, tmperr));
00161                 rsbac_kfree(tmp);
00162               }
00163             err = tmperr;
00164           }
00165       }
00166     return err;
00167   }
00168 
00169 /************************************************************************** */
00170 /* The lookup functions return NULL, if the item is not found, and a        */
00171 /* pointer to the item otherwise.                                           */
00172 
00173 /* first the device item lookup */
00174 static struct rsbac_mac_device_list_item_t * lookup_device(kdev_t kdev)
00175     {
00176       struct rsbac_mac_device_list_item_t  * curr = device_list_head.curr;
00177       
00178       /* if there is no current item or it is not the right one, search... */
00179       if(! (   curr
00180             && (RSBAC_MAJOR(curr->id) == RSBAC_MAJOR(kdev))
00181             && (RSBAC_MINOR(curr->id) == RSBAC_MINOR(kdev))
00182            )
00183         )
00184         {
00185           curr = device_list_head.head;
00186           while(   curr
00187                 && (   (RSBAC_MAJOR(curr->id) != RSBAC_MAJOR(kdev))
00188                     || (RSBAC_MINOR(curr->id) != RSBAC_MINOR(kdev))
00189                    )
00190                )
00191             {
00192               curr = curr->next;
00193             }
00194           if (curr)
00195             device_list_head.curr=curr;
00196         }
00197       /* it is the current item -> return it */
00198         return (curr);
00199     };
00200 
00201 /************************************************************************** */
00202 /* The add_item() functions add an item to the list, set head.curr to it,   */
00203 /* and return a pointer to the item.                                        */
00204 /* These functions will NOT check, if there is already an item under the    */
00205 /* same ID! If this happens, the lookup functions will return the old item! */
00206 /* All list manipulation is protected by rw-spinlocks to prevent inconsistency */
00207 /* and undefined behaviour in other concurrent functions.                   */
00208 
00209 /* Create a device item without adding to list. No locking needed. */
00210 static struct rsbac_mac_device_list_item_t 
00211           * create_device_item(kdev_t kdev)
00212     {
00213       struct rsbac_mac_device_list_item_t * new_item_p;
00214       int i;
00215 
00216       /* allocate memory for new device, return NULL, if failed */
00217       if ( !(new_item_p = (struct rsbac_mac_device_list_item_t *)
00218                     rsbac_kmalloc(sizeof(*new_item_p)) ) )
00219          return(NULL);
00220          
00221       new_item_p->id = kdev;
00222       new_item_p->mount_count = 1;
00223 
00224       /* init file/dir sublists */
00225       for(i=0 ; i < RSBAC_MAC_NR_TRU_FD_LISTS ; i++)
00226         new_item_p->handles[i] = NULL;
00227       return(new_item_p);
00228     };
00229 
00230 /* Add an existing device item to list. Locking needed. */
00231 static struct rsbac_mac_device_list_item_t 
00232           * add_device_item(struct rsbac_mac_device_list_item_t * device_p)
00233     {
00234       if (!device_p)
00235          return(NULL);
00236          
00237       /* add new device to device list */
00238       if (!device_list_head.head)
00239         { /* first device */
00240           device_list_head.head=device_p;
00241           device_list_head.tail=device_p;
00242           device_list_head.curr=device_p;
00243           device_list_head.count=1;
00244           device_p->prev=NULL;
00245           device_p->next=NULL;
00246         }  
00247       else
00248         { /* there is another device -> hang to tail */
00249           device_p->prev=device_list_head.tail;
00250           device_p->next=NULL;
00251           device_list_head.tail->next=device_p;
00252           device_list_head.tail=device_p;
00253           device_list_head.curr=device_p;
00254           device_list_head.count++;
00255         };
00256       return(device_p);
00257     };
00258 
00259 /************************************************************************** */
00260 /* The remove_item() functions remove an item from the list. If this item   */
00261 /* is head, tail or curr, these pointers are set accordingly.               */
00262 /* To speed up removing several subsequent items, curr is set to the next   */
00263 /* item, if possible.                                                       */
00264 /* If the item is not found, nothing is done.                               */
00265 
00266 static void clear_device_item(struct rsbac_mac_device_list_item_t * item_p)
00267     {
00268       if(!item_p)
00269         return;
00270 
00271       /* First deregister lists... */
00272       mac_detach_fd_lists(item_p);
00273       /* OK, lets remove the device item itself */
00274       rsbac_kfree(item_p);
00275     }; /* end of clear_device_item() */
00276 
00277 static void remove_device_item(kdev_t kdev)
00278     {
00279       struct rsbac_mac_device_list_item_t    * item_p;
00280 
00281       /* first we must locate the item. */
00282       if ( (item_p = lookup_device(kdev)) )
00283         { /* ok, item was found */
00284           if (device_list_head.head == item_p)  
00285              { /* item is head */
00286                if (device_list_head.tail == item_p)
00287                  { /* item is head and tail = only item -> list will be empty*/
00288                    device_list_head.head = NULL;
00289                    device_list_head.tail = NULL;
00290                  }
00291                else
00292                  { /* item is head, but not tail -> next item becomes head */
00293                    item_p->next->prev = NULL;
00294                    device_list_head.head = item_p->next;
00295                  };
00296              }
00297           else
00298              { /* item is not head */
00299                if (device_list_head.tail == item_p)
00300                  { /*item is not head, but tail -> previous item becomes tail*/
00301                    item_p->prev->next = NULL;
00302                    device_list_head.tail = item_p->prev;
00303                  }
00304                else
00305                  { /* item is neither head nor tail -> item is cut out */
00306                    item_p->prev->next = item_p->next;
00307                    item_p->next->prev = item_p->prev;
00308                  };
00309              };
00310              
00311           /* curr is no longer valid -> reset.                              */
00312           device_list_head.curr=NULL;
00313           /* adjust counter */
00314           device_list_head.count--;
00315           
00316           /* now we can remove the item from memory. This means cleaning up */
00317           /* everything below. */
00318           clear_device_item(item_p);
00319         };  /* end of if: item was found */
00320 
00321     }; /* end of remove_device_item() */
00322 
00323 /************************************************************************** */
00324 /* The copy_fp_tru_set_item() function copies a file cap set to a process   */
00325 /* cap set */
00326 
00327 static int copy_fp_tru_set_item(struct rsbac_mac_device_list_item_t * device_p,
00328                                 rsbac_mac_file_t    file,
00329                                 rsbac_pid_t pid)
00330     {
00331       rsbac_uid_t  * tru_item_p;
00332       rsbac_time_t * ttl_p;
00333       int i;
00334       long count;
00335       enum  rsbac_target_t target = T_FILE;
00336       union rsbac_target_id_t tid;
00337 
00338       rsbac_list_lol_remove(process_handle, &pid);
00339       count = rsbac_list_lol_get_all_subdesc_ttl(device_p->handles[fd_hash(file.inode)],
00340                                                  &file.inode,
00341                                                  (void **) &tru_item_p,
00342                                                  &ttl_p);
00343       if(   !count
00344          || (count == -RSBAC_ENOTFOUND)
00345         )
00346         {
00347           tid.file = file;
00348           if(!rsbac_get_parent(target, tid, &target, &tid))
00349             count = rsbac_list_lol_get_all_subdesc_ttl(device_p->handles[fd_hash(tid.file.inode)],
00350                                                        &tid.file.inode,
00351                                                        (void **) &tru_item_p,
00352                                                        &ttl_p);
00353         }
00354       if(count > 0)
00355         {
00356           for(i=0; i < count ; i++)
00357             {
00358               rsbac_list_lol_subadd_ttl(process_handle,
00359                                         ttl_p[i],
00360                                         &pid,
00361                                         &tru_item_p[i],
00362                                         NULL);
00363             }
00364           rsbac_vfree(tru_item_p);
00365           rsbac_vfree(ttl_p);
00366         }
00367       else
00368         {
00369           if(   (count < 0)
00370              && (count != -RSBAC_ENOTFOUND)
00371             )
00372             return count;
00373         }
00374 
00375       return 0;
00376     }; /* end of copy_fp_tru_set_item() */
00377 
00378 /************************************************************************** */
00379 /* The copy_pp_tru_set_item() function copies a process cap set to another  */
00380 
00381 static int copy_pp_tru_set_item_handle(rsbac_list_handle_t handle,
00382                                        rsbac_pid_t old_pid,
00383                                        rsbac_pid_t new_pid)
00384     {
00385       rsbac_uid_t  * tru_item_p;
00386       rsbac_time_t * ttl_p;
00387       int i;
00388       long count;
00389 
00390       rsbac_list_lol_remove(handle, &new_pid);
00391       count = rsbac_list_lol_get_all_subdesc_ttl(handle,
00392                                                  &old_pid,
00393                                                  (void **) &tru_item_p,
00394                                                  &ttl_p);
00395       if(count > 0)
00396         {
00397           for(i=0; i < count ; i++)
00398             {
00399               rsbac_list_lol_subadd_ttl(handle,
00400                                         ttl_p[i],
00401                                         &new_pid,
00402                                         &tru_item_p[i],
00403                                         NULL);
00404             }
00405           rsbac_vfree(tru_item_p);
00406           rsbac_vfree(ttl_p);
00407         }
00408       else
00409         {
00410           if(count < 0)
00411             return count;
00412         }
00413       return 0;
00414     }
00415 
00416 static int copy_pp_tru_set_item(rsbac_pid_t old_pid,
00417                                 rsbac_pid_t new_pid)
00418     {
00419       return copy_pp_tru_set_item_handle(process_handle, old_pid, new_pid);
00420     }; /* end of copy_pp_tru_set_item() */
00421 
00422 /************************************************* */
00423 /*               proc functions                    */
00424 /************************************************* */
00425 
00426 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
00427 static int
00428 mac_devices_proc_info(char *buffer, char **start, off_t offset, int length)
00429 {
00430   int len = 0;
00431   off_t pos   = 0;
00432   off_t begin = 0;
00433   struct rsbac_mac_device_list_item_t   * device_p;
00434   u_long dflags;
00435 
00436   if (!rsbac_is_initialized()) return (-ENOSYS);
00437 
00438   len += sprintf(buffer, "%u RSBAC MAC Devices\n-------------------\n",
00439                  device_list_head.count);
00440 
00441   /* wait for read access to device_list_head */
00442   rsbac_read_lock(&device_list_head.lock, &dflags);
00443   /* OK, go on */
00444   for (device_p = device_list_head.head; device_p; device_p = device_p->next)
00445     {
00446       len += sprintf(buffer + len, "%02u:%02u with mount_count = %u\n",
00447                      RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id),
00448                      device_p->mount_count);
00449       pos = begin + len;
00450       if (pos < offset)
00451         {
00452           len = 0;
00453           begin = pos;
00454         }
00455       if (pos > offset+length)
00456         break;
00457     }
00458   
00459   /* free access to device_list_head */
00460   rsbac_read_unlock(&device_list_head.lock, &dflags);
00461 
00462   *start = buffer + (offset - begin);
00463   len -= (offset - begin);
00464   
00465   if (len > length)
00466     len = length;
00467   return len;
00468 }
00469 
00470 static int
00471 stats_mac_proc_info(char *buffer, char **start, off_t offset, int length)
00472 {
00473     u_int len = 0;
00474     off_t pos   = 0;
00475     off_t begin = 0;
00476 
00477     u_int                                     tru_set_count = 0;
00478     u_int                                     member_count = 0;
00479     u_long dflags;
00480     struct rsbac_mac_device_list_item_t   * device_p;
00481     int i;
00482 
00483     union rsbac_target_id_t       rsbac_target_id;
00484     union rsbac_attribute_value_t rsbac_attribute_value;
00485 
00486     if (!rsbac_is_initialized())
00487       {
00488         rsbac_printk(KERN_WARNING "stats_mac_proc_info(): RSBAC not initialized\n");
00489         return(-RSBAC_ENOTINITIALIZED);
00490       }
00491 #ifdef CONFIG_RSBAC_DEBUG
00492     if (rsbac_debug_aef_mac)
00493       {
00494         rsbac_printk(KERN_DEBUG "stats_mac_proc_info(): calling ADF\n");
00495       }
00496 #endif
00497     rsbac_target_id.scd = ST_rsbac;
00498     rsbac_attribute_value.dummy = 0;
00499     if (!rsbac_adf_request(R_GET_STATUS_DATA,
00500                            current->pid,
00501                            T_SCD,
00502                            rsbac_target_id,
00503                            A_none,
00504                            rsbac_attribute_value))
00505       {
00506         return -EPERM;
00507       }
00508 
00509     len += sprintf(buffer, "MAC Status\n----------\n");
00510 
00511     len += sprintf(buffer + len, "%lu process trusted user set items, sum of %lu members\n",
00512                    rsbac_list_lol_count(process_handle),
00513                    rsbac_list_lol_all_subcount(process_handle));
00514     pos = begin + len;
00515     if (pos < offset)
00516       {
00517         len = 0;
00518         begin = pos;
00519       }
00520     if (pos > offset+length)
00521       goto out;
00522 
00523     /* protect device list */
00524     rsbac_read_lock(&device_list_head.lock, &dflags);
00525     device_p = device_list_head.head;
00526     while(device_p)
00527       {
00528         /* reset counters */
00529         tru_set_count = 0;
00530         member_count = 0;
00531         for(i=0 ; i < RSBAC_MAC_NR_TRU_FD_LISTS; i++)
00532           {
00533             tru_set_count += rsbac_list_lol_count(device_p->handles[i]);
00534             member_count += rsbac_list_lol_all_subcount(device_p->handles[i]);
00535           }
00536         len += sprintf(buffer + len, "device %02u:%02u has %u file trusted user set items, sum of %u members\n",
00537                        RSBAC_MAJOR(device_p->id),
00538                        RSBAC_MINOR(device_p->id),
00539                        tru_set_count,member_count);
00540         pos = begin + len;
00541         if (pos < offset)
00542           {
00543             len = 0;
00544             begin = pos;
00545           }
00546         if (pos > offset+length)
00547           goto out_unlock;
00548 
00549         device_p = device_p->next;
00550       }
00551 out_unlock:
00552     /* unprotect device list */
00553     rsbac_read_unlock(&device_list_head.lock, &dflags);
00554 
00555 out:
00556   *start = buffer + (offset - begin);
00557   len -= (offset - begin);
00558   
00559   if (len > length)
00560     len = length;
00561   return len;
00562 }
00563 
00564 static int
00565 mac_trulist_proc_info(char *buffer, char **start, off_t offset, int length)
00566 {
00567     u_int len = 0;
00568     off_t pos   = 0;
00569     off_t begin = 0;
00570 
00571     u_int                                      count = 0;
00572     u_int                                      member_count = 0;
00573     u_long                                     all_member_count;
00574     u_long dflags;
00575     int i,j,list;
00576     struct rsbac_mac_device_list_item_t   * device_p;
00577     rsbac_pid_t * p_list;
00578     rsbac_inode_nr_t * f_list;
00579     rsbac_uid_t * tru_list;
00580 
00581     union rsbac_target_id_t       rsbac_target_id;
00582     union rsbac_attribute_value_t rsbac_attribute_value;
00583 
00584     if (!rsbac_is_initialized())
00585       {
00586         rsbac_printk(KERN_WARNING "mac_trulist_proc_info(): RSBAC not initialized\n");
00587         return(-RSBAC_ENOTINITIALIZED);
00588       }
00589 #ifdef CONFIG_RSBAC_DEBUG
00590     if (rsbac_debug_aef_mac)
00591       {
00592         rsbac_printk(KERN_DEBUG "mac_trulist_proc_info(): calling ADF\n");
00593       }
00594 #endif
00595     rsbac_target_id.scd = ST_rsbac;
00596     rsbac_attribute_value.dummy = 0;
00597     if (!rsbac_adf_request(R_GET_STATUS_DATA,
00598                            current->pid,
00599                            T_SCD,
00600                            rsbac_target_id,
00601                            A_none,
00602                            rsbac_attribute_value))
00603       {
00604         return -EPERM;
00605       }
00606 
00607     len += sprintf(buffer, "MAC Trusted User Lists\n---------------------\n");
00608 
00609     /* protect process cap set list */
00610     len += sprintf(buffer + len, "Process trusted user sets:\nset-id  count   members");
00611     pos = begin + len;
00612     if (pos < offset)
00613       {
00614         len = 0;
00615         begin = pos;
00616       }
00617     if (pos > offset+length)
00618       goto out;
00619 
00620     all_member_count = 0;
00621     count = rsbac_list_lol_get_all_desc(process_handle,
00622                                         (void **) &p_list);
00623     if(count > 0)
00624       {
00625         for(i=0; i<count; i++)
00626           {
00627             member_count = rsbac_list_lol_get_all_subdesc(process_handle,
00628                                                           &p_list[i],
00629                                                           (void **) &tru_list);
00630             len += sprintf(buffer + len, "\n %u\t%u\t",
00631                            p_list[i],
00632                            member_count);
00633             if(member_count > 0)
00634               {
00635                 for(j=0; j<member_count; j++)
00636                   {
00637                     len += sprintf(buffer + len, "%u ",
00638                                    tru_list[j]);
00639                     pos = begin + len;
00640                     if (pos < offset)
00641                       {
00642                         len = 0;
00643                         begin = pos;
00644                       }
00645                     if (pos > offset+length)
00646                       {
00647                         rsbac_vfree(tru_list);
00648                         rsbac_vfree(p_list);
00649                         goto out;
00650                       }
00651                   }
00652                 rsbac_vfree(tru_list);
00653                 all_member_count += member_count;
00654               }
00655             pos = begin + len;
00656             if (pos < offset)
00657               {
00658                 len = 0;
00659                 begin = pos;
00660               }
00661             if (pos > offset+length)
00662               {
00663                 rsbac_vfree(p_list);
00664                 goto out;
00665               }
00666           }
00667         rsbac_vfree(p_list);
00668       }
00669     len += sprintf(buffer + len, "\n%u process trusted user set items, sum of %lu members\n",
00670                    count,all_member_count);
00671     pos = begin + len;
00672     if (pos < offset)
00673       {
00674         len = 0;
00675         begin = pos;
00676       }
00677     if (pos > offset+length)
00678       goto out;
00679 
00680     len += sprintf(buffer + len, "\nFile trusted user sets:\nset-id  count   members");
00681     pos = begin + len;
00682     if (pos < offset)
00683       {
00684         len = 0;
00685         begin = pos;
00686       }
00687     if (pos > offset+length)
00688       goto out;
00689 
00690     /* protect device list */
00691     rsbac_read_lock(&device_list_head.lock, &dflags);
00692     device_p = device_list_head.head;
00693     while(device_p)
00694       {
00695         /* reset counters */
00696         all_member_count = 0;
00697         for(list=0 ; list < RSBAC_MAC_NR_TRU_FD_LISTS; list++)
00698           {
00699             count = rsbac_list_lol_get_all_desc(device_p->handles[list],
00700                                                 (void **) &f_list);
00701             if(count > 0)
00702               {
00703                 for(i=0; i<count; i++)
00704                   {
00705                     member_count = rsbac_list_lol_get_all_subdesc(device_p->handles[list],
00706                                                                   &f_list[i],
00707                                                                   (void **) &tru_list);
00708                     len += sprintf(buffer + len, "\n %u\t%u\t",
00709                                    f_list[i],
00710                                    member_count);
00711                     if(member_count > 0)
00712                       {
00713                         for(j=0; j<member_count; j++)
00714                           {
00715                             len += sprintf(buffer + len, "%u ",
00716                                            tru_list[j]);
00717                             pos = begin + len;
00718                             if (pos < offset)
00719                               {
00720                                 len = 0;
00721                                 begin = pos;
00722                               }
00723                             if (pos > offset+length)
00724                               {
00725                                 rsbac_vfree(tru_list);
00726                                 rsbac_vfree(f_list);
00727                                 goto out_unlock;
00728                               }
00729                           }
00730                         rsbac_vfree(tru_list);
00731                         all_member_count += member_count;
00732                       }
00733                     pos = begin + len;
00734                     if (pos < offset)
00735                       {
00736                         len = 0;
00737                         begin = pos;
00738                       }
00739                     if (pos > offset+length)
00740                       {
00741                         rsbac_vfree(f_list);
00742                         goto out_unlock;
00743                       }
00744                   }
00745                 rsbac_vfree(f_list);
00746               }
00747           }
00748         len += sprintf(buffer + len, "\ndevice %02u:%02u has %u file trusted user set items, sum of %lu members\n",
00749                        RSBAC_MAJOR(device_p->id),
00750                        RSBAC_MINOR(device_p->id),
00751                        count, all_member_count);
00752         pos = begin + len;
00753         if (pos < offset)
00754           {
00755             len = 0;
00756             begin = pos;
00757           }
00758         if (pos > offset+length)
00759           goto out_unlock;
00760 
00761         device_p = device_p->next;
00762       }
00763 out_unlock:
00764     /* unprotect device list */
00765     rsbac_read_unlock(&device_list_head.lock, &dflags);
00766 
00767 out:
00768   *start = buffer + (offset - begin);
00769   len -= (offset - begin);
00770   
00771   if (len > length)
00772     len = length;
00773   return len;
00774 }
00775 #endif /* CONFIG_PROC_FS && CONFIG_RSBAC_PROC */
00776 
00777 /************************************************* */
00778 /*               Init functions                    */
00779 /************************************************* */
00780 
00781 /* All functions return 0, if no error occurred, and a negative error code  */
00782 /* otherwise. The error codes are defined in rsbac/error.h.                 */
00783 
00784 /************************************************************************** */
00785 /* Initialization of all MAC data structures. After this call, all MAC    */
00786 /* data is kept in memory for performance reasons, but is written to disk   */
00787 /* on every change. */
00788 
00789 /* Because there can be no access to aci data structures before init,       */
00790 /* rsbac_init_mac() will initialize all rw-spinlocks to unlocked.          */
00791 
00792 #ifdef CONFIG_RSBAC_INIT_DELAY
00793 int rsbac_init_mac(void)
00794 #else
00795 int __init rsbac_init_mac(void)
00796 #endif
00797   {
00798     int  err = 0;
00799     struct rsbac_mac_device_list_item_t * device_p = NULL;
00800     u_long dflags;
00801     struct proc_dir_entry * tmp_entry_p;
00802     struct rsbac_list_lol_info_t lol_info;
00803 
00804     if (rsbac_is_initialized())
00805       {
00806         rsbac_printk(KERN_WARNING "rsbac_init_mac(): RSBAC already initialized\n");
00807         return(-RSBAC_EREINIT);
00808       }
00809 
00810     /* set rw-spinlocks to unlocked status and init data structures */
00811     rsbac_printk(KERN_INFO "rsbac_init_mac(): Initializing RSBAC: MAC subsystem\n");
00812 
00813     lol_info.version = RSBAC_MAC_P_LIST_VERSION;
00814     lol_info.key = RSBAC_MAC_LIST_KEY;
00815     lol_info.desc_size = sizeof(rsbac_pid_t);
00816     lol_info.data_size = 0;
00817     lol_info.subdesc_size = sizeof(rsbac_uid_t);
00818     lol_info.subdata_size = 0;
00819     lol_info.max_age = 0;
00820     err = rsbac_list_lol_register(RSBAC_LIST_VERSION,
00821                                   &process_handle,
00822                                   &lol_info,
00823                                   RSBAC_LIST_DEF_DATA,
00824                                   NULL,
00825                                   NULL,
00826                                   NULL,
00827                                   NULL,
00828                                   NULL,
00829                                   NULL,
00830                                   RSBAC_MAC_P_LIST_NAME,
00831                                   RSBAC_AUTO_DEV);
00832     if(err)
00833       {
00834         char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
00835 
00836         if(tmp)
00837           {
00838             rsbac_printk(KERN_WARNING
00839                    "rsbac_init_mac(): Registering MAC process trusted user list failed with error %s\n",
00840                    get_error_name(tmp, err));
00841             rsbac_kfree(tmp);
00842           }
00843       }
00844 
00845     /* Init FD lists */
00846     device_list_head.lock = RW_LOCK_UNLOCKED;
00847     device_list_head.head = NULL;
00848     device_list_head.tail = NULL;
00849     device_list_head.curr = NULL;
00850     device_list_head.count = 0;
00851 
00852     /* read all data */
00853 #ifdef CONFIG_RSBAC_DEBUG
00854     if (rsbac_debug_ds_mac)
00855       {
00856         rsbac_printk(KERN_INFO "rsbac_init_mac(): Registering FD lists\n");
00857       }
00858 #endif
00859     device_p = create_device_item(rsbac_root_dev);
00860     if (!device_p)
00861       {
00862         rsbac_printk(KERN_CRIT "rsbac_init_mac(): Could not add device!\n");
00863         return(-RSBAC_ECOULDNOTADDDEVICE);
00864       }
00865     if((err = mac_register_fd_lists(device_p,rsbac_root_dev)))
00866       {
00867         char tmp[RSBAC_MAXNAMELEN];
00868 
00869         rsbac_printk(KERN_WARNING
00870                "rsbac_init_mac(): File/Dir trusted user set registration failed for dev %02u:%02u, err %s!\n",
00871                RSBAC_MAJOR(rsbac_root_dev), RSBAC_MINOR(rsbac_root_dev), get_error_name(tmp,err));
00872       }
00873     /* wait for write access to device_list_head */
00874     rsbac_write_lock_irq(&device_list_head.lock, &dflags);
00875     device_p = add_device_item(device_p);
00876     /* device was added, allow access */
00877     rsbac_write_unlock_irq(&device_list_head.lock, &dflags);
00878     if (!device_p)
00879       {
00880         rsbac_printk(KERN_CRIT "rsbac_init_mac(): Could not add device!\n");
00881         return(-RSBAC_ECOULDNOTADDDEVICE);
00882       }
00883 
00884     #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
00885     tmp_entry_p = create_proc_entry("mac_devices",
00886                                     S_IFREG | S_IRUGO | S_IWUGO,
00887                                     proc_rsbac_root_p);
00888     if(tmp_entry_p)
00889       {
00890         tmp_entry_p->get_info = mac_devices_proc_info;
00891       }
00892     tmp_entry_p = create_proc_entry("stats_mac",
00893                                     S_IFREG | S_IRUGO,
00894                                     proc_rsbac_root_p);
00895     if(tmp_entry_p)
00896       {
00897         tmp_entry_p->get_info = stats_mac_proc_info;
00898       }
00899     tmp_entry_p = create_proc_entry("mac_trusted",
00900                                     S_IFREG | S_IRUGO,
00901                                     proc_rsbac_root_p);
00902     if(tmp_entry_p)
00903       {
00904         tmp_entry_p->get_info = mac_trulist_proc_info;
00905       }
00906     #endif
00907 
00908 #ifdef CONFIG_RSBAC_DEBUG
00909     if (rsbac_debug_ds_mac)
00910       {
00911         rsbac_printk(KERN_DEBUG "rsbac_init_mac(): Ready.\n");
00912       }
00913 #endif
00914     return(err);
00915   };
00916 
00917 int rsbac_mount_mac(kdev_t kdev)
00918   {
00919     int err = 0;
00920     struct rsbac_mac_device_list_item_t * device_p;
00921     struct rsbac_mac_device_list_item_t * new_device_p;
00922     u_long dflags;
00923 
00924     if (!rsbac_is_initialized())
00925       {
00926         rsbac_printk(KERN_WARNING "rsbac_mount_mac(): RSBAC not initialized\n");
00927           return(-RSBAC_ENOTINITIALIZED);
00928       }
00929 #ifdef CONFIG_RSBAC_DEBUG
00930     if (rsbac_debug_ds_mac)
00931       {
00932         rsbac_printk(KERN_DEBUG "rsbac_mount_mac(): mounting device %02u:%02u\n",
00933                RSBAC_MAJOR(kdev),RSBAC_MINOR(kdev));
00934       }
00935 #endif
00936     /* wait for write access to device_list_head */
00937     rsbac_read_lock(&device_list_head.lock, &dflags);
00938     device_p = lookup_device(kdev);
00939     /* repeated mount? */
00940     if(device_p)
00941       {
00942         rsbac_printk(KERN_WARNING "rsbac_mount_mac: repeated mount %u of device %02u:%02u\n",
00943                device_p->mount_count, RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
00944         device_p->mount_count++;
00945         rsbac_read_unlock(&device_list_head.lock, &dflags);
00946         return 0;
00947       }
00948     rsbac_read_unlock(&device_list_head.lock, &dflags);
00949 
00950     new_device_p = create_device_item(kdev);
00951     if(!new_device_p)
00952       return -RSBAC_ECOULDNOTADDDEVICE;
00953 
00954     /* register lists */
00955     if((err = mac_register_fd_lists(new_device_p, kdev)))
00956       {
00957         char tmp[RSBAC_MAXNAMELEN];
00958 
00959         rsbac_printk(KERN_WARNING
00960                "rsbac_mount_mac(): File/Dir ACL registration failed for dev %02u:%02u, err %s!\n",
00961                RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev), get_error_name(tmp,err));
00962       }
00963 
00964     /* wait for read access to device_list_head */
00965     rsbac_read_lock(&device_list_head.lock, &dflags);
00966     /* make sure to only add, if this device item has not been added in the meantime */
00967     device_p = lookup_device(kdev);
00968     if(device_p)
00969       {
00970         rsbac_printk(KERN_WARNING
00971                "rsbac_mount_mac(): mount race for device %02u:%02u detected!\n",
00972                RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
00973         device_p->mount_count++;
00974         rsbac_read_unlock(&device_list_head.lock, &dflags);
00975         clear_device_item(new_device_p);
00976       }
00977     else
00978       {
00979         rsbac_read_unlock(&device_list_head.lock, &dflags);
00980         rsbac_write_lock_irq(&device_list_head.lock, &dflags);
00981         device_p = add_device_item(new_device_p);
00982         rsbac_write_unlock_irq(&device_list_head.lock, &dflags);
00983         if(!device_p)
00984           {
00985             rsbac_printk(KERN_WARNING "rsbac_mount_mac: adding device %02u:%02u failed!\n",
00986                    RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
00987             clear_device_item(new_device_p);
00988             err = -RSBAC_ECOULDNOTADDDEVICE;
00989           }
00990       }
00991     return(err);
00992   };
00993   
00994 /* When umounting a device, its file lists must be removed. */
00995 
00996 int rsbac_umount_mac(kdev_t kdev)
00997   {
00998     u_long flags;
00999     struct rsbac_mac_device_list_item_t * device_p;
01000 
01001     if (!rsbac_is_initialized())
01002       {
01003         rsbac_printk(KERN_WARNING "rsbac_umount(): RSBAC not initialized\n");
01004         return(-RSBAC_ENOTINITIALIZED);
01005       }
01006 
01007 #ifdef CONFIG_RSBAC_DEBUG
01008     if (rsbac_debug_ds_mac)
01009       {
01010         rsbac_printk(KERN_DEBUG "rsbac_umount_mac(): umounting device %02u:%02u\n",
01011                RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
01012       }
01013 #endif
01014     /* sync of attribute lists was done in rsbac_umount */
01015     /* wait for write access to device_list_head */
01016     rsbac_write_lock(&device_list_head.lock, &flags);
01017     /* OK, nobody else is working on it... */
01018     device_p = lookup_device(kdev);
01019     if(device_p)
01020       {
01021         if(device_p->mount_count == 1)
01022           remove_device_item(kdev);
01023         else
01024           {
01025             if(device_p->mount_count > 1)
01026               {
01027                 device_p->mount_count--;
01028               }
01029             else
01030               {
01031                 rsbac_printk(KERN_WARNING "rsbac_mount_mac: device %02u:%02u has mount_count < 1!\n",
01032                        RSBAC_MAJOR(kdev), RSBAC_MINOR(kdev));
01033               }
01034           }
01035       }
01036 
01037     /* allow access */
01038     rsbac_write_unlock(&device_list_head.lock, &flags);
01039     return(0);
01040   };
01041 
01042 /***************************************************/
01043 /* We also need some status information...         */
01044 
01045 int rsbac_stats_mac(void)
01046   {
01047     u_int                                     tru_set_count = 0;
01048     u_int                                     member_count = 0;
01049     u_long dflags;
01050     struct rsbac_mac_device_list_item_t   * device_p;
01051     int i;
01052   
01053     union rsbac_target_id_t       rsbac_target_id;
01054     union rsbac_attribute_value_t rsbac_attribute_value;
01055 
01056     if (!rsbac_is_initialized())
01057       {
01058         rsbac_printk(KERN_WARNING "rsbac_stats_mac(): RSBAC not initialized\n");
01059         return(-RSBAC_ENOTINITIALIZED);
01060       }
01061 #ifdef CONFIG_RSBAC_DEBUG
01062     if (rsbac_debug_aef_mac)
01063       {
01064         rsbac_printk(KERN_DEBUG "rsbac_stats_mac(): calling ADF\n");
01065       }
01066 #endif
01067     rsbac_target_id.scd = ST_rsbac;
01068     rsbac_attribute_value.dummy = 0;
01069     if (!rsbac_adf_request(R_GET_STATUS_DATA,
01070                            current->pid,
01071                            T_SCD,
01072                            rsbac_target_id,
01073                            A_none,
01074                            rsbac_attribute_value))
01075       {
01076         return -EPERM;
01077       }
01078 
01079     rsbac_printk(KERN_INFO "MAC Status\n----------\n");
01080 
01081     rsbac_printk(KERN_INFO "%lu process trusted user set items, sum of %lu members\n",
01082                    rsbac_list_lol_count(process_handle),
01083                    rsbac_list_lol_all_subcount(process_handle));
01084 
01085     /* protect device list */
01086     rsbac_read_lock(&device_list_head.lock, &dflags);
01087     device_p = device_list_head.head;
01088     while(device_p)
01089       {
01090         /* reset counters */
01091         tru_set_count = 0;
01092         member_count = 0;
01093         for(i=0 ; i < RSBAC_MAC_NR_TRU_FD_LISTS; i++)
01094           {
01095             tru_set_count += rsbac_list_lol_count(device_p->handles[i]);
01096             member_count += rsbac_list_lol_all_subcount(device_p->handles[i]);
01097           }
01098         rsbac_printk(KERN_INFO "device %02u:%02u has %u file trusted user set items, sum of %u members\n",
01099                          RSBAC_MAJOR(device_p->id),
01100                          RSBAC_MINOR(device_p->id),
01101                          tru_set_count,member_count);
01102         device_p = device_p->next;
01103       }
01104     /* unprotect device list */
01105     rsbac_read_unlock(&device_list_head.lock, &dflags);
01106     return(0);
01107   };
01108 
01109 /***************************************************/
01110 /* consistency checking (as far as possible)       */
01111 
01112 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
01113 int rsbac_check_mac(int correct, int check_inode)
01114   {
01115     struct rsbac_mac_device_list_item_t * device_p;
01116     u_long                              f_count = 0, f_sum = 0, tmp_count,
01117                                         r_count, u_count, b_count, no_member_count;
01118     long                                desc_count;
01119     u_int                               i,list_no;
01120     u_long                              dflags;
01121     struct super_block                * sb_p;
01122     struct inode                      * inode_p;
01123     rsbac_inode_nr_t                  * fd_desc_p;
01124   
01125     if (!rsbac_is_initialized())
01126       {
01127         rsbac_printk(KERN_WARNING "rsbac_check_mac(): RSBAC not initialized\n");
01128         return(-RSBAC_ENOTINITIALIZED);
01129       }
01130 
01131     /* wait for read access to device_list_head */
01132     rsbac_read_lock(&device_list_head.lock, &dflags);
01133     /* OK, go on */
01134 /*    rsbac_printk(KERN_INFO "rsbac_check_mac(): currently %u processes working on file/dir aci\n",
01135                      device_list_head.lock.lock); */
01136     device_p = device_list_head.head;
01137     while (device_p)
01138       { /* for all sublists */
01139         f_count = 0;
01140         r_count = 0;
01141         u_count = 0;
01142         b_count = 0;
01143         no_member_count = 0;
01144         if(check_inode)
01145           {
01146             sb_p = rsbac_get_super_block(device_p->id);
01147             if(!sb_p)
01148               {
01149                 rsbac_printk(KERN_WARNING "rsbac_check_mac(): no super block for device %02u:%02u!\n",
01150                        RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id));
01151               }
01152           }
01153         else
01154           sb_p = NULL;
01155 
01156         /* OK, go ahead */
01157         for(list_no = 0; list_no < RSBAC_MAC_NR_TRU_FD_LISTS; list_no++)
01158           {
01159 /*            rsbac_printk(KERN_INFO "rsbac_check_mac(): list %u\n",
01160                    list_no); */
01161             tmp_count = 0;
01162             desc_count = rsbac_list_lol_get_all_desc(device_p->handles[list_no], (void **) &fd_desc_p);
01163             if(desc_count > 0)
01164               {
01165                 for(i=0; i<desc_count; i++)
01166                   {
01167                     /* check for inode on disk (but not for reiserfs, because of 64bit inode numbers) */
01168                     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
01169                     if(sb_p)
01170                     #else
01171                     if(sb_p && !sb_p->s_op->read_inode2)
01172                     #endif
01173                       {
01174                         inode_p = iget(sb_p, fd_desc_p[i]);
01175                         if(is_bad_inode(inode_p))
01176                           { /* inode is bad -> remove */
01177                             b_count++;
01178                             if(correct)
01179                               {
01180                                 rsbac_printk(KERN_INFO
01181                                        "rsbac_check_mac(): fd_item for bad inode %u on device %02u:%02u, list %u, removing!\n",
01182                                         fd_desc_p[i], RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), list_no);
01183                                 rsbac_list_lol_remove(device_p->handles[list_no], &fd_desc_p[i]);
01184                                 continue;
01185                               }
01186                             else
01187                               {
01188                                 rsbac_printk(KERN_INFO
01189                                        "rsbac_check_mac(): fd_item for bad inode %u on device %02u:%02u, list %u!\n",
01190                                        fd_desc_p[i], RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), list_no);
01191                               }
01192                           } /* end of bad_inode */
01193                         else
01194                           { /* good inode */
01195                             /* currently only deletion checking of ext2 inodes is possible */
01196                             if(sb_p->s_magic == EXT2_SUPER_MAGIC)
01197                               {
01198                                 if(inode_p->u.ext2_i.i_dtime)
01199                                   { /* inode has been deleted -> remove */
01200                                     r_count++;
01201                                     if(correct)
01202                                       {
01203                                         rsbac_printk(KERN_INFO
01204                                                "rsbac_check_mac(): fd_item for deleted inode %u on device %02u:%02u, list %u, removing!\n",
01205                                                fd_desc_p[i], RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), list_no);
01206                                         rsbac_list_lol_remove(device_p->handles[list_no], &fd_desc_p[i]);
01207                                         continue;
01208                                       }
01209                                     else
01210                                       {
01211                                         rsbac_printk(KERN_INFO
01212                                                "rsbac_check_mac(): fd_item for deleted inode %u on device %02u:%02u, list %u!\n",
01213                                                fd_desc_p[i], RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), list_no);
01214                                       }
01215                                   }
01216                                 else
01217                                   {
01218                                     if(inode_p->i_nlink <= 0)
01219                                       { /* inode has been unlinked, but no dtime is set -> warn */
01220                                         u_count++;
01221                                         if(correct >= 2)
01222                                           {
01223                                             rsbac_printk(KERN_INFO
01224                                                    "rsbac_check_mac(): fd_item for inode %u with nlink <= 0 on device %02u:%02u, list %u, removing!\n",
01225                                                    fd_desc_p[i], RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), list_no);
01226                                             rsbac_list_lol_remove(device_p->handles[list_no], &fd_desc_p[i]);
01227                                             continue;
01228                                           }
01229                                         else
01230                                           {
01231                                             rsbac_printk(KERN_INFO
01232                                                    "rsbac_check_mac(): deleted inode %u on device %02u:%02u, list %u, has no dtime!\n",
01233                                                    fd_desc_p[i], RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), list_no);
01234                                           }
01235                                       }
01236                                   }
01237                               }
01238                           } /* end of is_good_inode */
01239                         iput(inode_p);
01240                       } /* end of sb_p */
01241                   }
01242                 tmp_count++;
01243                 rsbac_vfree(fd_desc_p);
01244                 f_count += desc_count;
01245               }
01246           } /* end of for-fd-list-array */
01247 
01248         switch(correct)
01249           {
01250             case 2:
01251               rsbac_printk(KERN_INFO
01252                      "rsbac_check_mac(): Device %02u:%02u has %lu file/dir trusted user sets (%lu removed (%lu bad inodes, %lu dtimed inodes, %lu unlinked inodes, %lu had no members and default mask))\n",
01253                      RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), f_count, b_count + r_count + u_count + no_member_count,
01254                      b_count, r_count, u_count, no_member_count);
01255               break;
01256             case 1:
01257               rsbac_printk(KERN_INFO
01258                      "rsbac_check_mac(): Device %02u:%02u has %lu file/dir trusted user sets (%lu removed (%lu bad inodes, %lu dtimed inodes, %lu had no members and default mask), %lu unlinked inodes)\n",
01259                      RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), f_count, b_count + r_count + no_member_count,
01260                      b_count, r_count, no_member_count, u_count);
01261               break;
01262             default:
01263               rsbac_printk(KERN_INFO
01264                      "rsbac_check_mac(): Device %02u:%02u has %lu file/dir trusted user sets (%lu with bad inodes, %lu with dtimed inodes, %lu unlinked inodes, %lu without members and with default mask)\n",
01265                      RSBAC_MAJOR(device_p->id), RSBAC_MINOR(device_p->id), f_count,
01266                      b_count, r_count, u_count, no_member_count);
01267           }
01268         f_sum += f_count;
01269         /* go on */
01270         device_p = device_p->next;
01271       }
01272     rsbac_printk(KERN_INFO "rsbac_check_mac(): Sum of %u Devices with %lu file/dir trusted user sets\n",
01273                  device_list_head.count, f_sum);
01274     /* free access to device_list_head */
01275     rsbac_read_unlock(&device_list_head.lock, &dflags);
01276     
01277     rsbac_printk(KERN_INFO
01278            "rsbac_check_mac(): Total of %lu registered mac items\n",
01279            f_sum);
01280     return(0);
01281   }
01282 #endif /* VERSION < 2.6.0 */
01283 
01284 /************************************************* */
01285 /*               Access functions                  */
01286 /************************************************* */
01287 
01288 /* All these procedures handle the rw-spinlocks to protect the targets during */
01289 /* access.                                                                  */
01290 /* Trying to access a never created or removed set returns an error! */
01291 
01292 /* rsbac_mac_add_to_truset */
01293 /* Add a set member to a set sublist. Set behaviour: also returns success, */
01294 /* if member was already in set! */
01295 
01296 int rsbac_mac_add_to_p_truset(
01297   rsbac_list_ta_number_t ta_number,
01298   rsbac_pid_t pid,
01299   rsbac_uid_t member,
01300   rsbac_time_t ttl)
01301   {
01302     if (!rsbac_is_initialized())
01303       {
01304         rsbac_printk(KERN_WARNING "rsbac_mac_add_to_p_truset(): RSBAC not initialized\n");
01305         return(-RSBAC_ENOTINITIALIZED);
01306       }
01307     if (in_interrupt())
01308       {
01309         rsbac_printk(KERN_WARNING "rsbac_mac_add_to_p_truset(): called from interrupt!\n");
01310       }
01311     return rsbac_ta_list_lol_subadd_ttl(ta_number, process_handle, ttl, &pid, &member, NULL);
01312   }
01313 
01314 int rsbac_mac_add_to_f_truset(
01315   rsbac_list_ta_number_t ta_number,
01316   rsbac_mac_file_t file,
01317   rsbac_uid_t member,
01318   rsbac_time_t ttl)
01319   {
01320     int                                     err=0;
01321     u_long dflags;
01322     struct rsbac_mac_device_list_item_t   * device_p;
01323 
01324     if (!rsbac_is_initialized())
01325       {
01326         rsbac_printk(KERN_WARNING "rsbac_mac_add_to_f_truset(): RSBAC not initialized\n");
01327         return(-RSBAC_ENOTINITIALIZED);
01328       }
01329     if (in_interrupt())
01330       {
01331         rsbac_printk(KERN_WARNING "rsbac_mac_add_to_f_truset(): called from interrupt!\n");
01332       }
01333 
01334     /* protect device list */
01335     rsbac_read_lock(&device_list_head.lock, &dflags);
01336     device_p = lookup_device(file.device);
01337     if(!device_p)
01338       {
01339         /* trigger rsbac_mount() */
01340         rsbac_read_unlock(&device_list_head.lock, &dflags);
01341         rsbac_get_super_block(file.device);
01342         /* retry */
01343         rsbac_read_lock(&device_list_head.lock, &dflags);
01344         device_p = lookup_device(file.device);
01345         if(!device_p)
01346           {
01347             rsbac_printk(KERN_WARNING "rsbac_mac_add_to_f_truset(): invalid device %02u:%02u!\n",
01348                    RSBAC_MAJOR(file.device),RSBAC_MINOR(file.device));
01349             rsbac_read_unlock(&device_list_head.lock, &dflags);
01350             return(-RSBAC_EINVALIDDEV);
01351           }
01352       }
01353 
01354     err = rsbac_ta_list_lol_subadd_ttl(ta_number,
01355                                        device_p->handles[fd_hash(file.inode)],
01356                                        ttl, &file.inode, &member, NULL);
01357     rsbac_read_unlock(&device_list_head.lock, &dflags);
01358     return(err);
01359   }
01360 
01361 /* rsbac_mac_remove_from_truset */
01362 /* Remove a set member from a sublist. Set behaviour: Returns no error, if */
01363 /* member is not in list.                                                  */
01364 
01365 int rsbac_mac_remove_from_p_truset(
01366   rsbac_list_ta_number_t ta_number,
01367   rsbac_pid_t pid,
01368   rsbac_uid_t member)
01369   {
01370     if (!rsbac_is_initialized())
01371       {
01372         rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_p_truset(): RSBAC not initialized\n");
01373         return(-RSBAC_ENOTINITIALIZED);
01374       }
01375     if (in_interrupt())
01376       {
01377         rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_p_truset(): called from interrupt!\n");
01378       }
01379     return rsbac_ta_list_lol_subremove(ta_number, process_handle, &pid, &member);
01380   }
01381 
01382 int rsbac_mac_remove_from_f_truset(
01383   rsbac_list_ta_number_t ta_number,
01384   rsbac_mac_file_t file,
01385   rsbac_uid_t member)
01386   {
01387     int                                    err=0;
01388     u_long dflags;
01389     struct rsbac_mac_device_list_item_t   * device_p;
01390 
01391     if (!rsbac_is_initialized())
01392       {
01393         rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_f_truset(): RSBAC not initialized\n");
01394         return(-RSBAC_ENOTINITIALIZED);
01395       }
01396     if (in_interrupt())
01397       {
01398         rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_f_truset(): called from interrupt!\n");
01399       }
01400 
01401     /* protect device list */
01402     rsbac_read_lock(&device_list_head.lock, &dflags);
01403     device_p = lookup_device(file.device);
01404     if(!device_p)
01405       {
01406         /* trigger rsbac_mount() */
01407         rsbac_read_unlock(&device_list_head.lock, &dflags);
01408         rsbac_get_super_block(file.device);
01409         /* retry */
01410         rsbac_read_lock(&device_list_head.lock, &dflags);
01411         device_p = lookup_device(file.device);
01412         if(!device_p)
01413           {
01414             rsbac_printk(KERN_WARNING "rsbac_mac_remove_from_f_truset(): invalid device %02u:%02u!\n",
01415                    RSBAC_MAJOR(file.device),RSBAC_MINOR(file.device));
01416             rsbac_read_unlock(&device_list_head.lock, &dflags);
01417             return(-RSBAC_EINVALIDDEV);
01418           }
01419       }
01420     err = rsbac_ta_list_lol_subremove(ta_number,
01421                                       device_p->handles[fd_hash(file.inode)],
01422                                       &file.inode,
01423                                       &member);
01424     rsbac_read_unlock(&device_list_head.lock, &dflags);
01425     return(err);
01426   }
01427 
01428 /* rsbac_mac_clear_truset */
01429 /* Remove all set members from a sublist. Set behaviour: Returns no error, */
01430 /* if list is empty.                                                       */
01431 
01432 int rsbac_mac_clear_p_truset(
01433   rsbac_list_ta_number_t ta_number,
01434   rsbac_pid_t pid)
01435   {
01436     if (!rsbac_is_initialized())
01437       {
01438         rsbac_printk(KERN_WARNING "rsbac_mac_clear_p_truset(): RSBAC not initialized\n");
01439         return(-RSBAC_ENOTINITIALIZED);
01440       }
01441     if (in_interrupt())
01442       {
01443         rsbac_printk(KERN_WARNING "rsbac_mac_clear_p_truset(): called from interrupt!\n");
01444       }
01445     return rsbac_ta_list_lol_remove(ta_number, process_handle, &pid);
01446   }
01447 
01448 int rsbac_mac_clear_f_truset(
01449   rsbac_list_ta_number_t ta_number,
01450   rsbac_mac_file_t file)
01451   {
01452     int                                    err=0;
01453     u_long dflags;
01454     struct rsbac_mac_device_list_item_t   * device_p;
01455 
01456     if (!rsbac_is_initialized())
01457       {
01458         rsbac_printk(KERN_WARNING "rsbac_mac_clear_f_truset(): RSBAC not initialized\n");
01459         return(-RSBAC_ENOTINITIALIZED);
01460       }
01461     if (in_interrupt())
01462       {
01463         rsbac_printk(KERN_WARNING "rsbac_mac_clear_f_truset(): called from interrupt!\n");
01464       }
01465     /* protect device list */
01466     rsbac_read_lock(&device_list_head.lock, &dflags);
01467     device_p = lookup_device(file.device);
01468     if(!device_p)
01469       {
01470         /* trigger rsbac_mount() */
01471         rsbac_read_unlock(&device_list_head.lock, &dflags);
01472         rsbac_get_super_block(file.device);
01473         /* retry */
01474         rsbac_read_lock(&device_list_head.lock, &dflags);
01475         device_p = lookup_device(file.device);
01476         if(!device_p)
01477           {
01478             rsbac_printk(KERN_WARNING "rsbac_mac_clear_f_truset(): invalid device %02u:%02u!\n",
01479                    RSBAC_MAJOR(file.device),RSBAC_MINOR(file.device));
01480             rsbac_read_unlock(&device_list_head.lock, &dflags);
01481             return(-RSBAC_EINVALIDDEV);
01482           }
01483       }
01484     err = rsbac_ta_list_lol_remove(ta_number, device_p->handles[fd_hash(file.inode)], &file.inode);
01485     rsbac_read_unlock(&device_list_head.lock, &dflags);
01486     return(err);
01487   }
01488 
01489 /* rsbac_mac_truset_member */
01490 /* Return truth value, whether member is in set */
01491 
01492 rsbac_boolean_t rsbac_mac_p_truset_member(
01493   rsbac_pid_t pid,
01494   rsbac_uid_t member)
01495   {
01496     if (!rsbac_is_initialized())
01497       {
01498         rsbac_printk(KERN_WARNING "rsbac_mac_p_truset_member(): RSBAC not initialized\n");
01499         return FALSE;
01500       }
01501     if (in_interrupt())
01502       {
01503         rsbac_printk(KERN_WARNING "rsbac_mac_p_truset_member(): called from interrupt!\n");
01504       }
01505     if(rsbac_list_lol_subexist(process_handle, &pid, &member))
01506       return TRUE;
01507     member = RSBAC_ALL_USERS;
01508     return rsbac_list_lol_subexist(process_handle, &pid, &member);
01509   }
01510 
01511 /* rsbac_mac_remove_truset */
01512 /* Remove a full set. For cleanup, if object is deleted. */
01513 /* To empty an existing set use rsbac_mac_clear_truset. */
01514 
01515 int rsbac_mac_remove_p_trusets(rsbac_pid_t pid)
01516   {
01517     return rsbac_mac_clear_p_truset(FALSE, pid);
01518   }
01519 
01520 int rsbac_mac_remove_f_trusets(rsbac_mac_file_t file)
01521   {
01522     return rsbac_mac_clear_f_truset(FALSE, file);
01523   }
01524 
01525 int rsbac_mac_copy_fp_truset(rsbac_mac_file_t    file,
01526                               rsbac_pid_t p_tru_set_id)
01527   {
01528     u_long dflags;
01529     struct rsbac_mac_device_list_item_t * device_p;
01530     int err=0;
01531 
01532     if (!rsbac_is_initialized())
01533       {
01534         rsbac_printk(KERN_WARNING "rsbac_mac_copy_fp_truset(): RSBAC not initialized\n");
01535         return(-RSBAC_ENOTINITIALIZED);
01536       }
01537     if (in_interrupt())
01538       {
01539         rsbac_printk(KERN_WARNING "rsbac_mac_copy_fp_truset(): called from interrupt!\n");
01540       }
01541 /*
01542 #ifdef CONFIG_RSBAC_DEBUG
01543     if (rsbac_debug_ds_mac)
01544       rsbac_printk(KERN_DEBUG
01545              "rsbac_mac_copy_fp_truset(): Copying file cap set data to process cap set\n");
01546 #endif
01547 */
01548     /* protect device list */
01549     rsbac_read_lock(&device_list_head.lock, &dflags);
01550     device_p = lookup_device(file.device);
01551     if(!device_p)
01552       {
01553         /* trigger rsbac_mount() */
01554         rsbac_read_unlock(&device_list_head.lock, &dflags);
01555         rsbac_get_super_block(file.device);
01556         /* retry */
01557         rsbac_read_lock(&device_list_head.lock, &dflags);
01558         device_p = lookup_device(file.device);
01559         if(!device_p)
01560           {
01561             rsbac_printk(KERN_WARNING "rsbac_mac_copy_fp_truset(): invalid device %02u:%02u!\n",
01562                    RSBAC_MAJOR(file.device),RSBAC_MINOR(file.device));
01563             rsbac_read_unlock(&device_list_head.lock, &dflags);
01564             return(-RSBAC_EINVALIDDEV);
01565           }
01566       }
01567     /* call the copy function */
01568     err = copy_fp_tru_set_item(device_p,file,p_tru_set_id);
01569     rsbac_read_unlock(&device_list_head.lock, &dflags);
01570     return(err);
01571   }
01572 
01573 int rsbac_mac_copy_pp_truset(rsbac_pid_t old_p_set_id,
01574                               rsbac_pid_t new_p_set_id)
01575   {
01576     if (!rsbac_is_initialized())
01577       {
01578         rsbac_printk(KERN_WARNING "rsbac_mac_copy_pp_truset(): RSBAC not initialized\n");
01579         return(-RSBAC_ENOTINITIALIZED);
01580       }
01581     if (in_interrupt())
01582       {
01583         rsbac_printk(KERN_WARNING "rsbac_mac_copy_pp_truset(): called from interrupt!\n");
01584       }
01585 /*
01586 #ifdef CONFIG_RSBAC_DEBUG
01587     if (rsbac_debug_ds_mac)
01588       rsbac_printk(KERN_DEBUG
01589              "rsbac_mac_copy_pp_truset(): Copying process cap set data to process cap set\n");
01590 #endif
01591 */
01592     /* call the copy function */
01593     return copy_pp_tru_set_item(old_p_set_id,new_p_set_id);
01594   }
01595 
01596 int rsbac_mac_get_f_trulist(
01597   rsbac_list_ta_number_t ta_number,
01598   rsbac_mac_file_t file,
01599   rsbac_uid_t **trulist_p,
01600   rsbac_time_t **ttllist_p)
01601   {
01602     u_long dflags;
01603     struct rsbac_mac_device_list_item_t * device_p;
01604     long count;
01605 
01606     if (!rsbac_is_initialized())
01607       {
01608         rsbac_printk(KERN_WARNING "rsbac_mac_get_f_trulist(): RSBAC not initialized\n");
01609         return(-RSBAC_ENOTINITIALIZED);
01610       }
01611     if (in_interrupt())
01612       {
01613         rsbac_printk(KERN_WARNING "rsbac_mac_get_f_trulist(): called from interrupt!\n");
01614       }
01615 /*
01616 #ifdef CONFIG_RSBAC_DEBUG
01617     if (rsbac_debug_ds_mac)
01618       rsbac_printk(KERN_DEBUG
01619              "rsbac_mac_get_f_trulist(): Getting file/dir trusted user set list\n");
01620 #endif
01621 */
01622     /* protect device list */
01623     rsbac_read_lock(&device_list_head.lock, &dflags);
01624     device_p = lookup_device(file.device);
01625     if(!device_p)
01626       {
01627         /* trigger rsbac_mount() */
01628         rsbac_read_unlock(&device_list_head.lock, &dflags);
01629         rsbac_get_super_block(file.device);
01630         /* retry */
01631         rsbac_read_lock(&device_list_head.lock, &dflags);
01632         device_p = lookup_device(file.device);
01633         if(!device_p)
01634           {
01635             rsbac_printk(KERN_WARNING "rsbac_mac_get_f_trulist(): invalid device %02u:%02u!\n",
01636                    RSBAC_MAJOR(file.device),RSBAC_MINOR(file.device));
01637             rsbac_read_unlock(&device_list_head.lock, &dflags);
01638             return(-RSBAC_EINVALIDDEV);
01639           }
01640       }
01641     count = rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
01642                                                   device_p->handles[fd_hash(file.inode)],
01643                                                   &file.inode,
01644                                                   (void **) trulist_p,
01645                                                   ttllist_p);
01646     rsbac_read_unlock(&device_list_head.lock, &dflags);
01647     return(count);
01648   }
01649 
01650 int rsbac_mac_get_p_trulist(
01651   rsbac_list_ta_number_t ta_number,
01652   rsbac_pid_t pid,
01653   rsbac_uid_t **trulist_p,
01654   rsbac_time_t **ttllist_p)
01655   {
01656     if (!rsbac_is_initialized())
01657       {
01658         rsbac_printk(KERN_WARNING "rsbac_mac_get_p_trulist(): RSBAC not initialized\n");
01659         return(-RSBAC_ENOTINITIALIZED);
01660       }
01661     if (in_interrupt())
01662       {
01663         rsbac_printk(KERN_WARNING "rsbac_mac_get_p_trulist(): called from interrupt!\n");
01664       }
01665 /*
01666 #ifdef CONFIG_RSBAC_DEBUG
01667     if (rsbac_debug_ds_mac)
01668       rsbac_printk(KERN_DEBUG
01669              "rsbac_mac_get_p_trulist(): Getting process trusted user set list\n");
01670 #endif
01671 */
01672     return rsbac_ta_list_lol_get_all_subdesc_ttl(ta_number,
01673                                                  process_handle,
01674                                                  &pid,
01675                                                  (void **) trulist_p,
01676                                                  ttllist_p);
01677   }
01678 
01679 /* end of mac_data_structures.c */

Generated on Sun May 21 14:30:54 2006 for RSBAC by  doxygen 1.4.2