dazuko_linux26.c

Go to the documentation of this file.
00001 /* Dazuko Linux. Allow Linux 2.6 file access control for 3rd-party applications.
00002    Copyright (c) 2003, 2004, 2005 H+BEDV Datentechnik GmbH
00003    Written by John Ogness <jogness@antivir.de>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU General Public License
00007    as published by the Free Software Foundation; either version 2
00008    of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software
00017    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 */
00019 
00020 #include "dazuko_linux26.h"
00021 #include "dazuko_core.h"
00022 #include "dazuko_linux26_device_def.h"
00023 
00024 #include <linux/config.h>
00025 #include <linux/module.h>
00026 #include <linux/kernel.h>
00027 #include <linux/init.h>
00028 #include <linux/vermagic.h>
00029 #include <linux/security.h>
00030 #include <linux/namei.h>
00031 #include <linux/dcache.h>
00032 #include <linux/mount.h>
00033 #include <linux/devfs_fs_kernel.h>
00034 #include <linux/device.h>
00035 #if !defined(USE_TRYTOFREEZEVOID) && !defined(USE_SUSPEND2)
00036 #include <linux/suspend.h>
00037 #endif
00038 #include <asm/uaccess.h>
00039 
00040 
00041 #ifndef DAZUKO_DM
00042 #define DAZUKO_DM 0
00043 #endif
00044 
00045 
00046 #define CHROOT_EVENT_STRING "chroot:"
00047 #define CHROOT_EVENT_LENGTH 7
00048 
00049 
00050 #ifndef WITH_LOCAL_DPATH
00051 extern char * __d_path(struct dentry *, struct vfsmount *, struct dentry *, struct vfsmount *, char *, int);
00052 #endif
00053 
00054 ssize_t linux_dazuko_device_read(struct file *, char __user *, size_t, loff_t *);
00055 ssize_t linux_dazuko_device_write(struct file *, const char __user *, size_t, loff_t *);
00056 int linux_dazuko_device_open(struct inode *, struct file *);
00057 int linux_dazuko_device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param);
00058 int linux_dazuko_device_release(struct inode *, struct file *);
00059 
00060 #ifdef USE_CLASS
00061 static struct class *dazuko_class = NULL;
00062 #else
00063 static struct class_simple *dazuko_class = NULL;
00064 #endif
00065 
00066 static struct vfsmount  *orig_rootmnt = NULL;
00067 static struct dentry    *orig_root = NULL;
00068 static int dev_major = -1;
00069 
00070 #ifndef DAZUKO_FIST
00071 #ifdef NO_STACKING_SUPPORT
00072 struct security_operations dazuko_security_ops;
00073 #else
00074 extern struct security_operations dazuko_security_ops;
00075 extern struct security_operations dazuko_register_security_ops;
00076 static struct security_operations dazuko_security_default_ops;
00077 #endif
00078 
00079 static int secondary_register = 0;
00080 
00081 static inline int dazuko_sys_generic(struct inode *inode, int mask, struct nameidata *nd);
00082 
00083 #ifndef NO_STACKING_SUPPORT
00084 int dazuko_register_security(const char *name, struct security_operations *ops);
00085 int dazuko_unregister_security(const char *name, struct security_operations *ops);
00086 #endif
00087 #endif
00088 
00089 #ifdef NO_CAPABILITIES
00090 int lsm_capability_compare(struct security_operations *ops1, struct security_operations *ops2);
00091 #endif
00092 
00093 static struct file_operations   fops = {
00094                 .owner          = THIS_MODULE,
00095                 .read           = linux_dazuko_device_read,
00096                 .write          = linux_dazuko_device_write,
00097                 .ioctl          = linux_dazuko_device_ioctl,
00098                 .open           = linux_dazuko_device_open,
00099                 .release        = linux_dazuko_device_release,
00100         };
00101 
00102 
00103 /* mutex */
00104 
00105 inline void xp_init_mutex(struct xp_mutex *mutex)
00106 {
00107         init_MUTEX(&(mutex->mutex));
00108 }
00109 
00110 inline void xp_down(struct xp_mutex *mutex)
00111 {
00112         down(&(mutex->mutex));
00113 }
00114 
00115 inline void xp_up(struct xp_mutex *mutex)
00116 {
00117         up(&(mutex->mutex));
00118 }
00119 
00120 inline void xp_destroy_mutex(struct xp_mutex *mutex)
00121 {
00122 }
00123 
00124 
00125 /* read-write lock */
00126 
00127 inline void xp_init_rwlock(struct xp_rwlock *rwlock)
00128 {
00129         rwlock_init(&(rwlock->rwlock));
00130 }
00131 
00132 inline void xp_write_lock(struct xp_rwlock *rwlock)
00133 {
00134         write_lock(&(rwlock->rwlock));
00135 }
00136 
00137 inline void xp_write_unlock(struct xp_rwlock *rwlock)
00138 {
00139         write_unlock(&(rwlock->rwlock));
00140 }
00141 
00142 inline void xp_read_lock(struct xp_rwlock *rlock)
00143 {
00144         read_lock(&(rlock->rwlock));
00145 }
00146 
00147 inline void xp_read_unlock(struct xp_rwlock *rlock)
00148 {
00149         read_unlock(&(rlock->rwlock));
00150 }
00151 
00152 inline void xp_destroy_rwlock(struct xp_rwlock *rwlock)
00153 {
00154 }
00155 
00156 
00157 /* wait-notify queue */
00158 
00159 inline int xp_init_queue(struct xp_queue *queue)
00160 {
00161         init_waitqueue_head(&(queue->queue));
00162         return 0;
00163 }
00164 
00165 inline int xp_wait_until_condition(struct xp_queue *queue, int (*cfunction)(void *), void *cparam, int allow_interrupt)
00166 {
00167         /* wait until cfunction(cparam) != 0 (condition is true) */
00168         int     ret = 0;
00169 
00170         if (allow_interrupt)
00171         {
00172                 while (1)
00173                 {
00174                         ret = wait_event_interruptible(queue->queue, cfunction(cparam) != 0);
00175 
00176 #ifdef USE_SUSPEND2
00177                         if (try_todo_list() == 0)
00178                                 break;
00179 #elif defined (USE_TRYTOFREEZEVOID)
00180                         if (try_to_freeze() == 0)
00181                                 break;
00182 #else
00183                         if (current->flags & PF_FREEZE)
00184                         {
00185                                 refrigerator(PF_FREEZE);
00186                         }
00187                         else
00188                         {
00189                                 break;
00190                         }
00191 #endif
00192                 }
00193         }
00194         else
00195         {
00196                 wait_event(queue->queue, cfunction(cparam) != 0);
00197         }
00198 
00199         return ret;
00200 }
00201 
00202 inline int xp_notify(struct xp_queue *queue)
00203 {
00204         wake_up(&(queue->queue));
00205         return 0;
00206 }
00207 
00208 inline int xp_destroy_queue(struct xp_queue *queue)
00209 {
00210         return 0;
00211 }
00212 
00213 
00214 /* memory */
00215 
00216 inline void* xp_malloc(size_t size)
00217 {
00218         return kmalloc(size, GFP_ATOMIC);
00219 }
00220 
00221 inline int xp_free(void *ptr)
00222 {
00223         kfree(ptr);
00224         return 0;
00225 }
00226 
00227 inline int xp_copyin(const void *user_src, void *kernel_dest, size_t size)
00228 {
00229         return copy_from_user(kernel_dest, user_src, size);
00230 }
00231 
00232 inline int xp_copyout(const void *kernel_src, void *user_dest, size_t size)
00233 {
00234         return copy_to_user(user_dest, kernel_src, size);
00235 }
00236 
00237 inline int xp_verify_user_writable(const void *user_ptr, size_t size)
00238 {
00239         return 0;
00240 }
00241 
00242 inline int xp_verify_user_readable(const void *user_ptr, size_t size)
00243 {
00244         return 0;
00245 }
00246 
00247 
00248 /* path attribute */
00249 
00250 inline int xp_is_absolute_path(const char *path)
00251 {
00252         if (path[0] == '/')
00253                 return 1;
00254 
00255 #ifdef USE_CHROOT
00256         if (dazuko_get_filename_length(path) >= CHROOT_EVENT_LENGTH)
00257         {
00258                 if (memcmp(CHROOT_EVENT_STRING, path, CHROOT_EVENT_LENGTH) == 0)
00259                         return 1;
00260         }
00261 #endif
00262 
00263         return 0;
00264 }
00265 
00266 
00267 /* atomic */
00268 
00269 inline int xp_atomic_set(struct xp_atomic *atomic, int value)
00270 {
00271         atomic_set(&(atomic->atomic), value);
00272         return 0;
00273 }
00274 
00275 inline int xp_atomic_inc(struct xp_atomic *atomic)
00276 {
00277         atomic_inc(&(atomic->atomic));
00278         return 0;
00279 }
00280 
00281 inline int xp_atomic_dec(struct xp_atomic *atomic)
00282 {
00283         atomic_dec(&(atomic->atomic));
00284         return 0;
00285 }
00286 
00287 inline int xp_atomic_read(struct xp_atomic *atomic)
00288 {
00289         return atomic_read(&(atomic->atomic));
00290 }
00291 
00292 
00293 /* file structure */
00294 
00295 #ifdef WITH_LOCAL_DPATH
00296 /* This code is taken directy from:
00297    linux-2.6.0/fs/dcache.c
00298    because __d_path is no longer exported.
00299  */
00300 /**
00301  * d_path - return the path of a dentry
00302  * @dentry: dentry to report
00303  * @vfsmnt: vfsmnt to which the dentry belongs
00304  * @root: root dentry
00305  * @rootmnt: vfsmnt to which the root dentry belongs
00306  * @buffer: buffer to return value in
00307  * @buflen: buffer length
00308  *
00309  * Convert a dentry into an ASCII path name. If the entry has been deleted
00310  * the string " (deleted)" is appended. Note that this is ambiguous.
00311  *
00312  * Returns the buffer or an error code if the path was too long.
00313  *
00314  * "buflen" should be positive. Caller holds the dcache_lock.
00315  */
00316 static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
00317                         struct dentry *root, struct vfsmount *rootmnt,
00318                         char *buffer, int buflen)
00319 {
00320         char * end = buffer+buflen;
00321         char * retval;
00322         int namelen;
00323 
00324         *--end = '\0';
00325         buflen--;
00326         if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
00327                 buflen -= 10;
00328                 end -= 10;
00329                 if (buflen < 0)
00330                         goto Elong;
00331                 memcpy(end, " (deleted)", 10);
00332         }
00333 
00334         if (buflen < 1)
00335                 goto Elong;
00336         /* Get '/' right */
00337         retval = end-1;
00338         *retval = '/';
00339 
00340         for (;;) {
00341                 struct dentry * parent;
00342 
00343                 if (dentry == root && vfsmnt == rootmnt)
00344                         break;
00345                 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
00346                         /* Global root? */
00347                         if (vfsmnt->mnt_parent == vfsmnt)
00348                                 goto global_root;
00349                         dentry = vfsmnt->mnt_mountpoint;
00350                         vfsmnt = vfsmnt->mnt_parent;
00351                         continue;
00352                 }
00353                 parent = dentry->d_parent;
00354                 prefetch(parent);
00355                 namelen = dentry->d_name.len;
00356                 buflen -= namelen + 1;
00357                 if (buflen < 0)
00358                         goto Elong;
00359                 end -= namelen;
00360                 memcpy(end, dentry->d_name.name, namelen);
00361                 *--end = '/';
00362                 retval = end;
00363                 dentry = parent;
00364         }
00365 
00366         return retval;
00367 
00368 global_root:
00369         namelen = dentry->d_name.len;
00370         buflen -= namelen;
00371         if (buflen < 0)
00372                 goto Elong;
00373         retval -= namelen-1;    /* hit the slash */
00374         memcpy(retval, dentry->d_name.name, namelen);
00375         return retval;
00376 Elong:
00377         return ERR_PTR(-ENAMETOOLONG);
00378 }
00379 #endif
00380 
00381 static int dazuko_get_full_filename(struct xp_file_struct *xfs)
00382 {
00383         struct vfsmount *rootmnt;
00384         struct dentry *root;
00385         char *temp;
00386 #ifdef USE_CHROOT
00387         int chrooted = 0;
00388 #endif
00389 
00390         if (xfs == NULL)
00391                 return 0;
00392 
00393         if (xfs->inode == NULL)
00394                 return 0;
00395 
00396 #ifndef DAZUKO_FIST
00397         if (S_ISDIR(xfs->inode->i_mode))
00398                 return 0;
00399 #endif
00400 
00401         if (xfs->nd == NULL || xfs->free_full_filename)
00402                 return 0;
00403         
00404         if (xfs->nd->mnt == NULL || xfs->nd->dentry == NULL)
00405                 return 0;
00406 
00407         /* check if we need to allocate a buffer */
00408         if (!xfs->free_page_buffer)
00409         {
00410                 /* get pre-requisites for d_path function */
00411                 xfs->buffer = (char *)__get_free_page(GFP_USER);
00412 
00413                 /* make sure we got a page */
00414                 if (xfs->buffer == NULL)
00415                         return 0;
00416 
00417                 /* the buffer will need to be freed */
00418                 xfs->free_page_buffer = 1;
00419         }
00420 
00421         /* make sure we don't already have a vfsmount */
00422         if (!xfs->mntput_vfsmount)
00423         {
00424                 xfs->vfsmount = mntget(xfs->nd->mnt);
00425 
00426                 /* the vfsmount will need to be put back */
00427                 xfs->mntput_vfsmount = 1;
00428         }
00429 
00430         /* make sure we don't already have a dentry */
00431         if (!xfs->dput_dentry)
00432         {
00433                 xfs->dentry = dget(xfs->nd->dentry);
00434 
00435                 /* the dentry will need to be put back */
00436                 xfs->dput_dentry = 1;
00437         }
00438 
00439         rootmnt = mntget(orig_rootmnt);
00440         root = dget(orig_root);
00441 
00442 #ifdef USE_CHROOT
00443         temp = d_path(xfs->dentry, xfs->vfsmount, xfs->buffer, PAGE_SIZE);
00444 
00445         if (orig_root != current->fs->root)
00446                 chrooted = 1;
00447 #else
00448         spin_lock(&dcache_lock);
00449         temp = __d_path(xfs->dentry, xfs->vfsmount, root, rootmnt, xfs->buffer, PAGE_SIZE);
00450         spin_unlock(&dcache_lock);
00451 #endif
00452 
00453         dput(root);
00454         mntput(rootmnt);
00455 
00456         /* make sure we really got a new filename */
00457         if (temp == NULL)
00458                 return 0;
00459         
00460         xfs->full_filename_length = dazuko_get_filename_length(temp);
00461 
00462 #ifdef USE_CHROOT
00463         if (chrooted)
00464                 xfs->full_filename_length += CHROOT_EVENT_LENGTH;
00465 #endif
00466         xfs->full_filename = (char *)xp_malloc(xfs->full_filename_length + 1);
00467         if (xfs->full_filename == NULL)
00468                 return 0;
00469         
00470         /* the char array will need to be freed */
00471         xfs->free_full_filename = 1;
00472 
00473 #ifdef USE_CHROOT
00474         if (chrooted)
00475         {
00476                 memcpy(xfs->full_filename, CHROOT_EVENT_STRING, CHROOT_EVENT_LENGTH + 1);
00477                 memcpy(xfs->full_filename + CHROOT_EVENT_LENGTH, temp, xfs->full_filename_length - CHROOT_EVENT_LENGTH + 1);
00478         }
00479         else
00480 #endif
00481         memcpy(xfs->full_filename, temp, xfs->full_filename_length + 1);
00482 
00483         /* we have a filename with the full path */
00484 
00485         return 1;
00486 }
00487 
00488 static int dazuko_fill_file_struct_cleanup(struct dazuko_file_struct *dfs)
00489 {
00490         if (dfs == NULL)
00491                 return 0;
00492 
00493         if (dfs->extra_data == NULL)
00494                 return 0;
00495 
00496         if (dfs->extra_data->free_page_buffer)
00497         {
00498                 free_page((unsigned long)dfs->extra_data->buffer);
00499                 dfs->extra_data->free_page_buffer = 0;
00500         }
00501 
00502         if (dfs->extra_data->dput_dentry)
00503         {
00504                 dput(dfs->extra_data->dentry);
00505                 dfs->extra_data->dput_dentry = 0;
00506         }
00507 
00508         if (dfs->extra_data->mntput_vfsmount)
00509         {
00510                 mntput(dfs->extra_data->vfsmount);
00511                 dfs->extra_data->mntput_vfsmount = 0;
00512         }
00513 
00514         return 0;
00515 }
00516 
00517 int xp_fill_file_struct(struct dazuko_file_struct *dfs)
00518 {
00519         int     error = -1;
00520 
00521         if (dfs == NULL)
00522                 return error;
00523 
00524         /* check if filename has already been filled in */
00525         if (dfs->filename != NULL)
00526                 return 0;
00527 
00528         /* make sure we can get the full path */
00529         if (dazuko_get_full_filename(dfs->extra_data))
00530         {
00531                 /* reference copy of full path */
00532                 dfs->filename = dfs->extra_data->full_filename;
00533 
00534                 dfs->filename_length = dfs->extra_data->full_filename_length;
00535 
00536                 dfs->file_p.size = dfs->extra_data->inode->i_size;
00537                 dfs->file_p.set_size = 1;
00538                 dfs->file_p.uid = dfs->extra_data->inode->i_uid;
00539                 dfs->file_p.set_uid = 1;
00540                 dfs->file_p.gid = dfs->extra_data->inode->i_gid;
00541                 dfs->file_p.set_gid = 1;
00542                 dfs->file_p.mode = dfs->extra_data->inode->i_mode;
00543                 dfs->file_p.set_mode = 1;
00544                 dfs->file_p.device_type = dfs->extra_data->inode->i_rdev;
00545                 dfs->file_p.set_device_type = 1;
00546 
00547                 error = 0;
00548         }
00549 
00550         dazuko_fill_file_struct_cleanup(dfs);
00551 
00552         return error;
00553 }
00554 
00555 static int dazuko_file_struct_cleanup(struct dazuko_file_struct **dfs)
00556 {
00557         if (dfs == NULL)
00558                 return 0;
00559 
00560         if (*dfs == NULL)
00561                 return 0;
00562 
00563         if ((*dfs)->extra_data)
00564         {
00565                 if ((*dfs)->extra_data->free_full_filename)
00566                         xp_free((*dfs)->extra_data->full_filename);
00567 
00568                 xp_free((*dfs)->extra_data);
00569         }
00570 
00571         xp_free(*dfs);
00572 
00573         *dfs = NULL;
00574 
00575         return 0;
00576 }
00577 
00578 
00579 /* daemon id */
00580 
00581 static inline int check_parent(struct task_struct *parent, struct task_struct *child)
00582 {
00583         struct task_struct      *ts = child;
00584 
00585         if (parent == NULL || child == NULL)
00586                 return -1;
00587 
00588         while (1)
00589         {
00590                 if (ts == parent)
00591                         return 0;
00592 
00593                 if (ts->parent == NULL)
00594                         break;
00595 
00596                 if (ts == ts->parent)
00597                         break;
00598 
00599                 ts = ts->parent;
00600         }
00601 
00602         return -1;
00603 }
00604 
00605 inline int xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2, int check_related)
00606 {
00607         if (id1 == NULL || id2 == NULL)
00608                 return DAZUKO_DIFFERENT;
00609 
00610         /* if file's are available and they match,
00611          * then we say that the id's match
00612          * ("file" is only used to unregister daemons and
00613          * here we allow other processes to do this)
00614          * Note: this is a Linux-only "hack" */
00615         if (id1->file != NULL && id1->file == id2->file)
00616                 return DAZUKO_SAME;
00617 
00618         if (id1->pid == id2->pid && id1->current_p == id2->current_p && id1->files == id2->files)
00619                 return DAZUKO_SAME;
00620 
00621         if (check_related)
00622         {
00623                 if (check_parent(id1->current_p, id2->current_p) == 0)
00624                 {
00625                         return DAZUKO_CHILD;
00626                 }
00627                 else if (id1->pid == id2->pid || id1->current_p == id2->current_p || id1->files == id2->files)
00628                 {
00629                         return DAZUKO_SUSPICIOUS;
00630                 }
00631         }
00632 
00633         return DAZUKO_DIFFERENT;
00634 }
00635 
00636 inline int xp_id_free(struct xp_daemon_id *id)
00637 {
00638         xp_free(id);
00639 
00640         return 0;
00641 }
00642 
00643 inline struct xp_daemon_id* xp_id_copy(struct xp_daemon_id *id)
00644 {
00645         struct xp_daemon_id     *ptr;
00646 
00647         if (id == NULL)
00648                 return NULL;
00649 
00650         ptr = (struct xp_daemon_id *)xp_malloc(sizeof(struct xp_daemon_id));
00651 
00652         if (ptr != NULL)
00653         {
00654                 ptr->pid = id->pid;
00655                 ptr->file = id->file;
00656                 ptr->current_p = id->current_p;
00657                 ptr->files = id->files;
00658         }
00659 
00660         return ptr;
00661 }
00662 
00663 
00664 /* event */
00665 
00666 int xp_set_event_properties(struct event_properties *event_p, struct xp_daemon_id *xp_id)
00667 {
00668         event_p->pid = xp_id->pid;
00669         event_p->set_pid = 1;
00670 
00671         return 0;
00672 }
00673 
00674 
00675 /* cache settings */
00676 
00677 int xp_init_cache(unsigned long ttl)
00678 {
00679         return -1;
00680 }
00681 
00682 
00683 /* system hooks */
00684 
00685 #ifndef DAZUKO_FIST
00686 #ifndef NO_STACKING_SUPPORT
00687 int dazuko_register_security(const char *name, struct security_operations *ops)
00688 {
00689         char *daz_p;
00690         char *ext_p;
00691         char *def_p;
00692         char *end_p;
00693         void **ext_func_p;
00694         void **def_func_p;
00695         void **daz_func_p;
00696         void *ext_func;
00697         void *def_func;
00698         void *daz_func;
00699         int error = 0;
00700 
00701         if (name == NULL || ops == NULL)
00702                 return XP_ERROR_PERMISSION;
00703 
00704         /* basic allignment checking (there should only be function
00705          * pointers in this structure)
00706          */
00707         if (sizeof(struct security_operations) % sizeof(void *) != 0)
00708                 return XP_ERROR_FAULT;
00709 
00710         /* first check if all requested hooks are available */
00711 
00712         /* note: ops is filled with default functions for functions
00713          *       that were specified with NULL
00714          */
00715 
00716 #ifdef NO_CAPABILITIES
00717         /* we have do do an extra check if there are no capabilities
00718          * because we never hooked these functions (see dazuko_linux26_lsm.h)
00719          */
00720 
00721         if (lsm_capability_compare(ops, &dazuko_security_default_ops) != 0)
00722                 return XP_ERROR_PERMISSION;
00723 #endif
00724 
00725         ext_p = (char *)ops;
00726         def_p = (char *)&dazuko_security_default_ops;
00727         daz_p = (char *)&dazuko_security_ops;
00728         end_p = daz_p + sizeof(dazuko_security_ops);
00729 
00730         while (daz_p < end_p)
00731         {
00732                 daz_func_p = (void **)daz_p;
00733                 ext_func_p = (void **)ext_p;
00734                 def_func_p = (void **)def_p;
00735 
00736                 daz_func = *daz_func_p;
00737                 ext_func = *ext_func_p;
00738                 def_func = *def_func_p;
00739 
00740                 if (ext_func != def_func && daz_func != NULL)
00741                 {
00742                         error = 1;
00743                         break;
00744                 }
00745 
00746                 daz_p += sizeof(void *);
00747                 ext_p += sizeof(void *);
00748                 def_p += sizeof(void *);
00749         }
00750 
00751         if (error)
00752         {
00753                 /* some requested hooks are not available */
00754 
00755                 return XP_ERROR_PERMISSION;
00756         }
00757 
00758         /* install the requested hooks */
00759 
00760         ext_p = (char *)ops;
00761         def_p = (char *)&dazuko_security_default_ops;
00762         daz_p = (char *)&dazuko_security_ops;
00763         end_p = daz_p + sizeof(dazuko_security_ops);
00764 
00765         while (daz_p < end_p)
00766         {
00767                 daz_func_p = (void **)daz_p;
00768                 ext_func_p = (void **)ext_p;
00769                 def_func_p = (void **)def_p;
00770 
00771                 daz_func = *daz_func_p;
00772                 ext_func = *ext_func_p;
00773                 def_func = *def_func_p;
00774                 
00775                 if (ext_func != def_func && daz_func == NULL)
00776                 {
00777                         *daz_func_p = ext_func;
00778                 }
00779 
00780                 daz_p += sizeof(void *);
00781                 ext_p += sizeof(void *);
00782                 def_p += sizeof(void *);
00783         }
00784 
00785         return 0;
00786 }
00787 
00788 int dazuko_unregister_security(const char *name, struct security_operations *ops)
00789 {
00790         char *daz_p;
00791         char *ext_p;
00792         char *def_p;
00793         char *end_p;
00794         void **ext_func_p;
00795         void **def_func_p;
00796         void **daz_func_p;
00797         void *ext_func;
00798         void *def_func;
00799         void *daz_func;
00800 
00801         if (name == NULL || ops == NULL)
00802                 return XP_ERROR_PERMISSION;
00803 
00804         /* basic allignment checking (there should only be function
00805          * pointers in this structure)
00806          */
00807         if (sizeof(struct security_operations) % sizeof(void *) != 0)
00808                 return XP_ERROR_FAULT;
00809 
00810         /* first check if all requested hooks are available */
00811 
00812         ext_p = (char *)ops;
00813         def_p = (char *)&dazuko_security_default_ops;
00814         daz_p = (char *)&dazuko_security_ops;
00815         end_p = daz_p + sizeof(dazuko_security_ops);
00816 
00817         while (daz_p < end_p)
00818         {
00819                 daz_func_p = (void **)daz_p;
00820                 ext_func_p = (void **)ext_p;
00821                 def_func_p = (void **)def_p;
00822 
00823                 daz_func = *daz_func_p;
00824                 ext_func = *ext_func_p;
00825                 def_func = *def_func_p;
00826 
00827                 if (ext_func != def_func && daz_func == ext_func)
00828                 {
00829                         *daz_func_p = NULL;
00830                 }
00831 
00832                 daz_p += sizeof(void *);
00833                 ext_p += sizeof(void *);
00834                 def_p += sizeof(void *);
00835         }
00836 
00837         return 0;
00838 }
00839 #endif
00840 #endif
00841 
00842 
00843 #ifdef DAZUKO_FIST
00844 int dazuko_sys_generic(int event, struct inode *inode, struct nameidata *nd, int daemon_is_allowed)
00845 #else
00846 static inline int dazuko_sys_generic(struct inode *inode, int mask, struct nameidata *nd)
00847 #endif
00848 {
00849         struct dazuko_file_struct *dfs = NULL;
00850         int error = 0;
00851         int check_error = 0;
00852         struct event_properties event_p;
00853         struct xp_daemon_id xp_id;
00854         struct slot_list *sl = NULL;
00855 #ifndef DAZUKO_FIST
00856         int event = DAZUKO_ON_OPEN;
00857         int daemon_is_allowed = 1;
00858 #endif
00859 
00860         dazuko_bzero(&event_p, sizeof(event_p));
00861 
00862 #ifdef DAZUKO_FIST
00863         if (inode == NULL || nd == NULL)
00864                 return XP_ERROR_PERMISSION;
00865 #else
00866         if ((mask & MAY_EXEC) != 0)
00867         {
00868                 event = DAZUKO_ON_EXEC;
00869                 daemon_is_allowed = 0;
00870         }
00871         else
00872         {
00873                 /* mask == 0 is passed in when a file is created */
00874                 if (mask == 0 || (mask & (MAY_WRITE|MAY_APPEND)) != 0)
00875                 {
00876                         if ((mask & MAY_READ) != 0)
00877                         {
00878                                 event_p.flags = O_RDWR;
00879                         }
00880                         else
00881                         {
00882                                 event_p.flags = O_WRONLY;
00883                         }
00884 
00885                         event_p.set_flags = 1;
00886                 }
00887                 else if ((mask & MAY_READ) != 0)
00888                 {
00889                         event_p.flags = O_RDONLY;
00890                         event_p.set_flags = 1;
00891                 }
00892         }
00893 #endif
00894 
00895         xp_id.pid = current->pid;
00896         xp_id.file = NULL;
00897         xp_id.current_p = current;
00898         xp_id.files = current->files;
00899 
00900         check_error = dazuko_check_access(event, daemon_is_allowed, &xp_id, &sl);
00901 
00902         if (!check_error)
00903         {
00904                 event_p.mode = inode->i_mode;
00905                 event_p.set_mode = 1;
00906                 event_p.pid = current->pid;
00907                 event_p.set_pid = 1;
00908                 event_p.uid = current->uid;
00909                 event_p.set_uid = 1;
00910 
00911                 dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
00912                 if (dfs != NULL)
00913                 {
00914                         dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
00915 
00916                         dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
00917                         if (dfs->extra_data != NULL)
00918                         {
00919                                 dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
00920 
00921                                 dfs->extra_data->nd = nd;
00922                                 dfs->extra_data->inode = inode;
00923 
00924                                 error = dazuko_process_access(event, dfs, &event_p, sl);
00925                         }
00926                         else
00927                         {
00928                                 xp_free(dfs);
00929                                 dfs = NULL;
00930                         }
00931 
00932                         dazuko_file_struct_cleanup(&dfs);
00933                 }
00934         }
00935 
00936         if (error)
00937                 return XP_ERROR_PERMISSION;
00938 
00939         return 0;
00940 }
00941 
00942 inline int xp_sys_hook()
00943 {
00944 #ifndef DAZUKO_FIST
00945 #ifndef NO_STACKING_SUPPORT
00946         struct security_operations dummy_ops;
00947         int got_dummy = 0;
00948 #endif
00949 
00950         /* Make sure we have a valid task_struct. */
00951 
00952         if (current == NULL)
00953         {
00954                 xp_print("dazuko: panic (current == NULL)\n");
00955                 return -1;
00956         }
00957         if (current->fs == NULL)
00958         {
00959                 xp_print("dazuko: panic (current->fs == NULL)\n");
00960                 return -1;
00961         }
00962         if (current->fs->root == NULL)
00963         {
00964                 xp_print("dazuko: panic (current->fs->root == NULL)\n");
00965                 return -1;
00966         }
00967         if (current->fs->rootmnt == NULL)
00968         {
00969                 xp_print("dazuko: panic (current->fs->rootmnt == NULL)\n");
00970                 return -1;
00971         }
00972 
00973 
00974 #ifdef USE_CHROOT
00975         xp_print("dazuko: info: using chroot events for chroot'd processes\n");
00976 #endif
00977 #if defined(CONFIG_SMP) && defined(WITH_LOCAL_DPATH)
00978         xp_print("dazuko: warning: using local __dpath() dangerous for SMP kernels\n");
00979 #endif
00980 #endif
00981 
00982         /* Grab the current root. This is assumed to be the real.
00983          * If it is not the real root, we could have problems
00984          * looking up filenames. */
00985 
00986         read_lock(&current->fs->lock);
00987         orig_rootmnt = current->fs->rootmnt;
00988         orig_root = current->fs->root;
00989         read_unlock(&current->fs->lock);
00990 
00991 #ifndef DAZUKO_FIST
00992 #ifdef NO_STACKING_SUPPORT
00993         memset(&dazuko_security_ops, 0, sizeof(dazuko_security_ops));
00994         dazuko_security_ops.inode_permission = dazuko_sys_generic;
00995 
00996         if (register_security(&dazuko_security_ops) != 0)
00997         {
00998                 if (mod_reg_security(DEVICE_NAME, &dazuko_security_ops) != 0)
00999                 {
01000                         xp_print("dazuko: failed to register\n");
01001                         return XP_ERROR_INVALID;
01002                 }
01003 
01004                 secondary_register = 1;
01005                 xp_print("dazuko: warning: registered as secondary module\n");
01006         }
01007 #else
01008         /* grab security defaults if we can */
01009 
01010         memset(&dazuko_security_default_ops, 0, sizeof(dazuko_security_default_ops));
01011 
01012         memset(&dummy_ops, 0, sizeof(dummy_ops));
01013         if (register_security(&dummy_ops) == 0)
01014         {
01015                 memcpy(&dazuko_security_default_ops, &dummy_ops, sizeof(dazuko_security_default_ops));
01016                 unregister_security(&dummy_ops);
01017 
01018                 got_dummy = 1;
01019         }
01020 
01021         /* register with the security manager */
01022 
01023         memset(&dazuko_security_ops, 0, sizeof(dazuko_security_ops));
01024         dazuko_security_ops.inode_permission = dazuko_sys_generic;
01025 
01026         if (!got_dummy || register_security(&dazuko_register_security_ops) != 0)
01027         {
01028                 /* register as secondary, but with no stacking support */
01029                 if (mod_reg_security(DEVICE_NAME, &dazuko_security_ops) != 0)
01030                 {
01031                         xp_print("dazuko: failed to register\n");
01032                         return XP_ERROR_INVALID;
01033                 }
01034 
01035                 secondary_register = 1;
01036                 xp_print("dazuko: warning: registered as secondary module\n");
01037         }
01038 #endif
01039 #endif
01040 
01041         dev_major = register_chrdev(DAZUKO_DM, DEVICE_NAME, &fops);
01042         if (dev_major < 0)
01043         {
01044                 xp_print("dazuko: unable to register device, err=%d\n", dev_major);
01045                 return dev_major;
01046         }
01047 
01048         devfs_mk_cdev(MKDEV(dev_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, DEVICE_NAME);
01049 
01050 #ifdef USE_CLASS
01051         dazuko_class = class_create(THIS_MODULE, "dazuko");
01052 #ifdef CLASS_class_device_create_2_6_15
01053         class_device_create(dazuko_class, NULL, MKDEV(dev_major, 0), NULL, "dazuko");
01054 #else
01055         class_device_create(dazuko_class, MKDEV(dev_major, 0), NULL, "dazuko");
01056 #endif
01057 #else
01058         dazuko_class = class_simple_create(THIS_MODULE, "dazuko");
01059         class_simple_device_add(dazuko_class, MKDEV(dev_major, 0), NULL, "dazuko");
01060 #endif
01061 
01062         return 0;
01063 }
01064 
01065 inline int xp_sys_unhook()
01066 {
01067         unregister_chrdev(dev_major, DEVICE_NAME);
01068 
01069         devfs_remove(DEVICE_NAME);
01070 
01071 #ifdef USE_CLASS
01072         class_device_destroy(dazuko_class, MKDEV(dev_major, 0));
01073         class_destroy(dazuko_class);
01074 #else
01075         class_simple_device_remove(MKDEV(dev_major, 0));
01076         class_simple_destroy(dazuko_class);
01077 #endif
01078 
01079 #ifndef DAZUKO_FIST
01080 #ifdef NO_STACKING_SUPPORT
01081         if (secondary_register)
01082                 mod_unreg_security(DEVICE_NAME, &dazuko_security_ops);
01083         else
01084                 unregister_security(&dazuko_security_ops);
01085 #else
01086         if (secondary_register)
01087                 mod_unreg_security(DEVICE_NAME, &dazuko_security_ops);
01088         else
01089                 unregister_security(&dazuko_register_security_ops);
01090 #endif
01091 #endif
01092 
01093         return 0;
01094 }
01095 
01096 
01097 /* output */
01098 
01099 int xp_print(const char *fmt, ...)
01100 {
01101         va_list args;
01102         char *p;
01103         size_t size = 1024;
01104         int length;
01105 
01106         p = (char *)xp_malloc(size);
01107         if (p == NULL)
01108                 return -1;
01109 
01110         length = dazuko_get_filename_length(KERN_INFO);
01111 
01112         memcpy(p, KERN_INFO, length);
01113 
01114         va_start(args, fmt);
01115         vsnprintf(p + length, size - length, fmt, args);
01116         va_end(args);
01117 
01118         p[size-1] = 0;
01119 
01120         printk(p);
01121 
01122         xp_free(p);
01123 
01124         return 0;
01125 }
01126 
01127 
01128 /* ioctl's */
01129 
01130 int linux_dazuko_device_open(struct inode *inode, struct file *file)
01131 {
01132         DPRINT(("dazuko: linux_dazuko_device_open() [%d]\n", current->pid));
01133 
01134         return 0;
01135 }
01136 
01137 ssize_t linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos)
01138 {
01139         /* Reading from the dazuko device simply
01140          * returns the device number. This is to
01141          * help out the daemon. */
01142 
01143         char    tmp[20];
01144         size_t  dev_major_len;
01145 
01146         DPRINT(("dazuko: linux_dazuko_device_read() [%d]\n", current->pid));
01147         
01148         if (*pos != 0)
01149                 return 0;
01150 
01151         if (dev_major < 0)
01152                 return XP_ERROR_NODEVICE;
01153 
01154         /* print dev_major to a string
01155          * and get length (with terminator) */
01156         dazuko_bzero(tmp, sizeof(tmp));
01157 
01158         dev_major_len = dazuko_snprintf(tmp, sizeof(tmp), "%d", dev_major) + 1;
01159 
01160         if (tmp[sizeof(tmp)-1] != 0)
01161         {
01162                 xp_print("dazuko: failing device_read, device number overflow for dameon %d (dev_major=%d)\n", current->pid, dev_major);
01163                 return XP_ERROR_FAULT;
01164         }
01165 
01166         if (length < dev_major_len)
01167                 return XP_ERROR_INVALID;
01168 
01169         /* copy dev_major string to userspace */
01170         if (xp_copyout(tmp, buffer, dev_major_len) != 0)
01171                 return XP_ERROR_FAULT;
01172 
01173         *pos += dev_major_len;
01174 
01175         return dev_major_len;
01176 }
01177 
01178 ssize_t linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos)
01179 {
01180         struct xp_daemon_id     xp_id;
01181         char                    tmpbuffer[32];
01182         int                     size;
01183 
01184         size = length;
01185         if (length >= sizeof(tmpbuffer))
01186                 size = sizeof(tmpbuffer) -1;
01187 
01188         /* copy request pointer string to kernelspace */
01189         if (xp_copyin(buffer, tmpbuffer, size) != 0)
01190                 return XP_ERROR_FAULT;
01191 
01192         tmpbuffer[size] = 0;
01193 
01194         xp_id.pid = current->pid;
01195         xp_id.file = file;
01196         xp_id.current_p = current;
01197         xp_id.files = current->files;
01198 
01199         if (dazuko_handle_user_request(tmpbuffer, &xp_id) == 0)
01200                 return size;
01201 
01202         return XP_ERROR_INTERRUPT;
01203 }
01204 
01205 int linux_dazuko_device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param)
01206 {
01207         /* A daemon uses this function to interact with
01208          * the kernel. A daemon can set scanning parameters,
01209          * give scanning response, and get filenames to scan. */
01210 
01211         struct xp_daemon_id     xp_id;
01212         int                     error = 0;
01213 
01214         if (param == 0)
01215         {
01216                 xp_print("dazuko: error: linux_dazuko_device_ioctl(..., 0)\n");
01217                 return XP_ERROR_INVALID;
01218         }
01219 
01220         xp_id.pid = current->pid;
01221         xp_id.file = file;
01222         xp_id.current_p = current;
01223         xp_id.files = current->files;
01224 
01225         error = dazuko_handle_user_request_compat1((void *)param, _IOC_NR(cmd), &xp_id);
01226 
01227         if (error != 0)
01228         {
01229                 /* general error occurred */
01230 
01231                 return XP_ERROR_PERMISSION;
01232         }
01233 
01234         return error;
01235 }
01236 
01237 int linux_dazuko_device_release(struct inode *inode, struct file *file)
01238 {
01239         struct xp_daemon_id     xp_id;
01240 
01241         DPRINT(("dazuko: dazuko_device_release() [%d]\n", current->pid));
01242 
01243         xp_id.pid = current->pid;
01244         xp_id.file = file;
01245         xp_id.current_p = current;
01246         xp_id.files = current->files;
01247 
01248         return dazuko_unregister_daemon(&xp_id);
01249 }
01250 
01251 
01252 /* init/exit */
01253 
01254 static int __init linux_dazuko_init(void)
01255 {
01256         return dazuko_init();
01257 }
01258 
01259 static void __exit linux_dazuko_exit(void)
01260 {
01261         dazuko_exit();
01262 }
01263 
01264 
01265 MODULE_AUTHOR("H+BEDV Datentechnik GmbH <linux_support@antivir.de>");
01266 MODULE_DESCRIPTION("allow 3rd-party file access control");
01267 MODULE_LICENSE("GPL");
01268 MODULE_INFO(vermagic, VERMAGIC_STRING);
01269 
01270 #ifdef DAZUKO_FIST
01271 EXPORT_SYMBOL(dazuko_sys_generic);
01272 #endif
01273 
01274 security_initcall(linux_dazuko_init);
01275 module_exit(linux_dazuko_exit);

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