dazuko_linux.c

Go to the documentation of this file.
00001 /* Dazuko Linux. Allow Linux file access control for 3rd-party applications.
00002    Copyright (c) 2002, 2003, 2004, 2005 H+BEDV Datentechnik GmbH
00003    Written by Martin Ritter <mritter@antivir.de>
00004               John Ogness <jogness@antivir.de>
00005 
00006    This program is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU General Public License
00008    as published by the Free Software Foundation; either version 2
00009    of the License, or (at your option) any later version.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 */
00020 
00021 /*
00022 TODO:
00023 sys calls (cleanup compile warnings)
00024 validate code
00025 */
00026 
00027 #include "dazuko_linux.h"
00028 #include "dazuko_core.h"
00029 
00030 #ifdef DEVFS_SUPPORT
00031 #include <linux/devfs_fs_kernel.h>
00032 #endif
00033 
00034 #ifndef DAZUKO_DM
00035 #define DAZUKO_DM 0
00036 #endif
00037 
00038 #ifdef HIDDEN_SCT
00039 void **sys_call_table;
00040 extern asmlinkage long sys_exit(int error_code);
00041 #else
00042 extern void *sys_call_table[];
00043 #endif
00044 
00045 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
00046 int linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos);
00047 int linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos);
00048 #else
00049 ssize_t linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos);
00050 ssize_t linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos);
00051 #endif
00052 int linux_dazuko_device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param);
00053 int linux_dazuko_device_open(struct inode *inode, struct file *file);
00054 int linux_dazuko_device_release(struct inode *inode, struct file *file);
00055 
00056 extern struct xp_atomic active;
00057 
00058 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00059 static struct vfsmount  *orig_rootmnt = NULL;
00060 #endif
00061         
00062 static struct dentry    *orig_root = NULL;
00063 static int              dev_major = -1;
00064 
00065 #if defined(ON_OPEN_SUPPORT)
00066 static asmlinkage long          (*original_sys_open)(const char *filename, int flags, int mode);
00067 static asmlinkage long          (*original_sys_dup)(unsigned int filedes);
00068 #endif
00069 #if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
00070 static asmlinkage long          (*original_sys_dup2)(unsigned int oldfd, unsigned int newfd);
00071 #endif
00072 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
00073 static asmlinkage long          (*original_sys_close)(unsigned int fd);
00074 #endif
00075 #ifdef ON_EXEC_SUPPORT
00076 static asmlinkage int           (*original_sys_execve)(struct pt_regs regs);
00077 #endif
00078 #ifdef ON_UNLINK_SUPPORT
00079 static asmlinkage long          (*original_sys_unlink)(const char *pathname);
00080 #endif
00081 #ifdef ON_RMDIR_SUPPORT
00082 static asmlinkage long          (*original_sys_rmdir)(const char *pathname);
00083 #endif
00084 
00085 static struct file_operations   fops = {
00086                                         read: linux_dazuko_device_read,         /* read */
00087                                         write: linux_dazuko_device_write,       /* write */
00088                                         ioctl: linux_dazuko_device_ioctl,       /* ioctl */
00089                                         open: linux_dazuko_device_open,         /* open */
00090                                         release: linux_dazuko_device_release,   /* release */
00091                                 };
00092 
00093 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
00094 
00095 /* The following code is taken directly from Linux in the file:
00096    include/linux/sched.h */
00097 
00098 #ifndef __wait_event_interruptible
00099 #define __wait_event_interruptible(wq, condition, ret)           \
00100 do {                                                             \
00101         struct wait_queue __wait;                                \
00102                                                                  \
00103         __wait.task = current;                                   \
00104         add_wait_queue(&wq, &__wait);                            \
00105         for (;;) {                                               \
00106                 current->state = TASK_INTERRUPTIBLE;             \
00107                 mb();                                            \
00108                 if (condition)                                   \
00109                         break;                                   \
00110                 if (!signal_pending(current)) {                  \
00111                         schedule();                              \
00112                         continue;                                \
00113                 }                                                \
00114                 ret = -ERESTARTSYS;                              \
00115                 break;                                           \
00116         }                                                        \
00117         current->state = TASK_RUNNING;                           \
00118         remove_wait_queue(&wq, &__wait);                         \
00119 } while (0)
00120 #endif
00121 
00122 #ifndef wait_event_interruptible
00123 #define wait_event_interruptible(wq, condition)                  \
00124 ({                                                               \
00125         int __ret = 0;                                           \
00126         if (!(condition))                                        \
00127                 __wait_event_interruptible(wq, condition, __ret);\
00128         __ret;                                                   \
00129 })
00130 #define wait_event(wq, condition)                                \
00131 ({                                                               \
00132         int __ret = 0;                                           \
00133         if (!(condition))                                        \
00134                 __wait_event_interruptible(wq, condition, __ret);\
00135         __ret;                                                   \
00136 })
00137 #endif
00138 
00139 #endif
00140 
00141 
00142 /* mutex */
00143 
00144 inline void xp_init_mutex(struct xp_mutex *mutex)
00145 {
00146         #ifdef init_MUTEX
00147                 init_MUTEX(&(mutex->mutex));
00148         #else
00149                 sema_init(&(mutex->mutex), 1);
00150         #endif
00151 }
00152 
00153 inline void xp_down(struct xp_mutex *mutex)
00154 {
00155         down(&(mutex->mutex));
00156 }
00157 
00158 inline void xp_up(struct xp_mutex *mutex)
00159 {
00160         up(&(mutex->mutex));
00161 }
00162 
00163 inline void xp_destroy_mutex(struct xp_mutex *mutex)
00164 {
00165 }
00166 
00167 
00168 /* read-write lock */
00169 
00170 inline void xp_init_rwlock(struct xp_rwlock *rwlock)
00171 {
00172         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00173                 rwlock_init(&(rwlock->rwlock));
00174         #else
00175                 rwlock->rwlock = RW_LOCK_UNLOCKED;
00176         #endif
00177 }
00178 
00179 inline void xp_write_lock(struct xp_rwlock *rwlock)
00180 {
00181         write_lock(&(rwlock->rwlock));
00182 }
00183 
00184 inline void xp_write_unlock(struct xp_rwlock *rwlock)
00185 {
00186         write_unlock(&(rwlock->rwlock));
00187 }
00188 
00189 inline void xp_read_lock(struct xp_rwlock *rlock)
00190 {
00191         read_lock(&(rlock->rwlock));
00192 }
00193 
00194 inline void xp_read_unlock(struct xp_rwlock *rlock)
00195 {
00196         read_unlock(&(rlock->rwlock));
00197 }
00198 
00199 inline void xp_destroy_rwlock(struct xp_rwlock *rwlock)
00200 {
00201 }
00202 
00203 
00204 /* wait-notify queue */
00205 
00206 inline int xp_init_queue(struct xp_queue *queue)
00207 {
00208 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00209         init_waitqueue_head(&(queue->queue));
00210 #else
00211         queue = NULL;
00212 #endif
00213 
00214         return 0;
00215 }
00216 
00217 inline int xp_wait_until_condition(struct xp_queue *queue, int (*cfunction)(void *), void *cparam, int allow_interrupt)
00218 {
00219         /* wait until cfunction(cparam) != 0 (condition is true) */
00220 
00221         if (allow_interrupt)
00222         {
00223                 return wait_event_interruptible(queue->queue, cfunction(cparam) != 0);
00224         }
00225         else
00226         {
00227                 wait_event(queue->queue, cfunction(cparam) != 0);
00228         }
00229 
00230         return 0;
00231 }
00232 
00233 inline int xp_notify(struct xp_queue *queue)
00234 {
00235         wake_up(&(queue->queue));
00236         return 0;
00237 }
00238 
00239 inline int xp_destroy_queue(struct xp_queue *queue)
00240 {
00241         return 0;
00242 }
00243 
00244 
00245 /* memory */
00246 
00247 inline void* xp_malloc(size_t size)
00248 {
00249         return kmalloc(size, GFP_KERNEL);
00250 }
00251 
00252 inline int xp_free(void *ptr)
00253 {
00254         kfree(ptr);
00255         return 0;
00256 }
00257 
00258 inline int xp_copyin(const void *user_src, void *kernel_dest, size_t size)
00259 {
00260         return copy_from_user(kernel_dest, user_src, size);
00261 }
00262 
00263 inline int xp_copyout(const void *kernel_src, void *user_dest, size_t size)
00264 {
00265         return copy_to_user(user_dest, kernel_src, size);
00266 }
00267 
00268 inline int xp_verify_user_writable(const void *user_ptr, size_t size)
00269 {
00270         #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
00271                 return verify_area(VERIFY_WRITE, user_ptr, size);
00272         #else
00273                 return 0;
00274         #endif
00275 }
00276 
00277 inline int xp_verify_user_readable(const void *user_ptr, size_t size)
00278 {
00279         #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
00280                 return verify_area(VERIFY_READ, user_ptr, size);
00281         #else
00282                 return 0;
00283         #endif
00284 }
00285 
00286 
00287 /* path attribute */
00288 
00289 inline int xp_is_absolute_path(const char *path)
00290 {
00291         return (path[0] == '/');
00292 }
00293 
00294 
00295 /* atomic */
00296 
00297 inline int xp_atomic_set(struct xp_atomic *atomic, int value)
00298 {
00299         atomic_set(&(atomic->atomic), value);
00300         return 0;
00301 }
00302 
00303 inline int xp_atomic_inc(struct xp_atomic *atomic)
00304 {
00305 #ifdef MODULE
00306         if (atomic == &active)
00307                 MOD_INC_USE_COUNT;
00308 #endif
00309 
00310         atomic_inc(&(atomic->atomic));
00311         return 0;
00312 }
00313 
00314 inline int xp_atomic_dec(struct xp_atomic *atomic)
00315 {
00316 #ifdef MODULE
00317         if (atomic == &active)
00318                 MOD_DEC_USE_COUNT;
00319 #endif
00320 
00321         atomic_dec(&(atomic->atomic));
00322         return 0;
00323 }
00324 
00325 inline int xp_atomic_read(struct xp_atomic *atomic)
00326 {
00327         return atomic_read(&(atomic->atomic));
00328 }
00329 
00330 
00331 /* file structure */
00332 
00333 static int dazuko_get_filename_dentry(struct xp_file_struct *xfs, int follow_symlinks, const char *local_filename, int user_ptr)
00334 {
00335         /* We get the appropriate structures in order
00336          * to acquire the inode and store them in the
00337          * dazuko_file_struct structure. */
00338 
00339         const char      *filename = NULL;
00340         int             putname_filename = 0;
00341         int             filename_length = 0;
00342         int             rc = 0;
00343 
00344         /* make sure we really need to get the filename */
00345         if (user_ptr)
00346         {
00347                 /* grab filename from filename cache */
00348                 filename = (char *)getname(local_filename);
00349 
00350                 /* make sure it is a valid name */
00351                 if (IS_ERR(filename))
00352                 {
00353                         filename = NULL;
00354                         return 0;
00355                 }
00356 
00357                 /* the name will need to be put back */
00358                 putname_filename = 1;
00359         }
00360         else
00361         {
00362                 filename = local_filename;
00363         }
00364 
00365         filename_length = dazuko_get_filename_length(filename);
00366 
00367         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00368         {
00369                 dazuko_bzero(&(xfs->nd), sizeof(struct nameidata));
00370 
00371                 /* initialize nameidata structure for finding file data */
00372                 if (!path_init(filename, (follow_symlinks ? LOOKUP_FOLLOW : 0) | LOOKUP_POSITIVE, &(xfs->nd)))
00373                         goto dentry_exit;
00374 
00375                 if (!xfs->path_release_nd)
00376                 {
00377                         /* find file data and fill it in nameidata structure */
00378                         if (path_walk(filename, &(xfs->nd)))  /* !=0 -> error */
00379                                 goto dentry_exit;
00380 
00381                         /* the nameidata will need to be released */
00382                         xfs->path_release_nd = 1;
00383                 }
00384 
00385                 /* get a local copy of the dentry to make kernel version
00386                  * compatibility code eaiser to read */
00387 
00388                 /* make sure we don't already have a dentry */
00389                 if (!xfs->dput_dentry)
00390                 {
00391                         xfs->dentry = dget(xfs->nd.dentry);
00392 
00393                         /* the dentry will need to be put back */
00394                         xfs->dput_dentry = 1;
00395                 }
00396         }
00397         #else
00398         {
00399                 if (!xfs->dput_dentry)
00400                 {
00401                         xfs->dentry = lookup_dentry(filename, NULL, (follow_symlinks ? LOOKUP_FOLLOW : 0));
00402                         if (IS_ERR(xfs->dentry))
00403                         {
00404                                 xfs->dentry = NULL;
00405                                 goto dentry_exit;
00406                         }
00407 
00408                         /* the dentry will need to be put back */
00409                         xfs->dput_dentry = 1;
00410                 }
00411         }
00412         #endif
00413 
00414         /* check if this file has no inode */
00415         if (xfs->dentry->d_inode == NULL)
00416         {
00417                 goto dentry_exit;
00418         }
00419         else
00420         {
00421                 /* if we made it this far, we got the inode */
00422                 rc = 1;
00423         }
00424 
00425 dentry_exit:
00426         if (putname_filename)
00427                 putname(filename);
00428 
00429         return rc;
00430 }
00431 
00432 static int dazuko_get_fd_dentry(struct xp_file_struct *xfs)
00433 {
00434         if (current->files != NULL)
00435         {
00436                 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00437                 {
00438                         read_lock(&current->files->file_lock);
00439                 }
00440                 #endif
00441 
00442                 if (current->files->fd != NULL)
00443                 {
00444                         if (current->files->fd[xfs->fd] != NULL)
00445                         {
00446                                 if (current->files->fd[xfs->fd]->f_dentry != NULL)
00447                                 {
00448                                         xfs->dentry = dget(current->files->fd[xfs->fd]->f_dentry);
00449                                         xfs->dput_dentry = 1;
00450 
00451                                         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00452                                         {
00453                                                 if (current->files->fd[xfs->fd]->f_vfsmnt != NULL)
00454                                                 {
00455                                                         xfs->vfsmount = mntget(current->files->fd[xfs->fd]->f_vfsmnt);
00456                                                         xfs->mntput_vfsmount = 1;
00457                                                 }
00458                                                 else
00459                                                 {
00460                                                         dput(xfs->dentry);
00461                                                         xfs->dentry = NULL;
00462                                                         xfs->dput_dentry = 0;
00463                                                 }
00464                                         }
00465                                         #endif
00466                                 }
00467                         }
00468                 }
00469 
00470                 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00471                 {
00472                         read_unlock(&current->files->file_lock);
00473                 }
00474                 #endif
00475         }
00476 
00477         /* check if we got the dentry */
00478         if (xfs->dentry == NULL)
00479                 return 0;
00480 
00481         /* check if this file has no inode */
00482         if (xfs->dentry->d_inode == NULL)
00483                 return 0;
00484 
00485         return 1;
00486 }
00487 
00488 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
00489 static char * __d_path(struct dentry *dentry, struct dentry *root, char *buffer, int buflen)
00490 {
00491         /* Copy of d_path from linux/dcache.c but using
00492          * a given root instead of the current root. */
00493 
00494         char * end = buffer+buflen;
00495         char * retval;
00496 
00497         *--end = '\0';
00498         buflen--;
00499         if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
00500                 buflen -= 10;
00501                 end -= 10;
00502                 memcpy(end, " (deleted)", 10);
00503         }
00504 
00505         /* Get '/' right */
00506         retval = end-1;
00507         *retval = '/';
00508 
00509         for (;;) {
00510                 struct dentry * parent;
00511                 int namelen;
00512 
00513                 if (dentry == root)
00514                         break;
00515                 dentry = dentry->d_covers;
00516                 parent = dentry->d_parent;
00517                 if (dentry == parent)
00518                         break;
00519                 namelen = dentry->d_name.len;
00520                 buflen -= namelen + 1;
00521                 if (buflen < 0)
00522                         break;
00523                 end -= namelen;
00524                 memcpy(end, dentry->d_name.name, namelen);
00525                 *--end = '/';
00526                 retval = end;
00527                 dentry = parent;
00528         }
00529         return retval;
00530 }
00531 #endif
00532 
00533 static int dazuko_get_full_filename(struct xp_file_struct *xfs)
00534 {
00535         /* Get the filename with the full path appended
00536          * to the beginning. */
00537 
00538         char            *temp;
00539         struct dentry   *root;
00540 
00541         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00542                 struct vfsmount *rootmnt;
00543         #endif
00544 
00545         /* check if we need to allocate a buffer */
00546         if (!xfs->free_page_buffer)
00547         {
00548                 /* get pre-requisites for d_path function */
00549                 xfs->buffer = (char *)__get_free_page(GFP_USER);
00550 
00551                 /* the buffer will need to be freed */
00552                 xfs->free_page_buffer = 1;
00553         }
00554 
00555         root = dget(orig_root);
00556 
00557         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00558         {
00559                 /* make sure we don't already have a vfsmount */
00560                 if (!xfs->mntput_vfsmount)
00561                 {
00562                         xfs->vfsmount = mntget(xfs->nd.mnt);
00563 
00564                         /* the vfsmount will need to be put back */
00565                         xfs->mntput_vfsmount = 1;
00566                 }
00567 
00568                 /* build new filename with path included, using temp */
00569 
00570                 rootmnt = mntget(orig_rootmnt);
00571 
00572                 spin_lock(&dcache_lock);
00573                 temp = __d_path(xfs->dentry, xfs->vfsmount, root, rootmnt, xfs->buffer, PAGE_SIZE);
00574                 spin_unlock(&dcache_lock);
00575 
00576                 mntput(rootmnt);
00577         }
00578         #else
00579         {
00580                 /* build new filename with path included, using temp */
00581 
00582                 temp = __d_path(xfs->dentry, root, xfs->buffer, PAGE_SIZE);
00583         }
00584         #endif
00585 
00586         dput(root);
00587 
00588         /* make sure we really got a new filename */
00589         if (temp == NULL)
00590                 return 0;
00591 
00592         /* make sure we don't already have a full_filename */
00593         if (!xfs->free_full_filename)
00594         {
00595                 xfs->full_filename_length = dazuko_get_filename_length(temp);
00596 
00597                 xfs->full_filename = (char *)xp_malloc(xfs->full_filename_length + 1);
00598                 if (!xfs->full_filename)
00599                         return 0;
00600 
00601                 /* the char array will need to be freed */
00602                 xfs->free_full_filename = 1;
00603 
00604                 memcpy(xfs->full_filename, temp, xfs->full_filename_length + 1);
00605         }
00606 
00607         /* we have a filename with the full path */
00608 
00609         return 1;
00610 }
00611 
00612 static inline int dazuko_fill_file_struct_cleanup(struct dazuko_file_struct *dfs)
00613 {
00614         /* Delete all the flagged structures from the
00615          * given dazuko_file_struct and reset all critical
00616          * values back to 0. */
00617 
00618         if (dfs->extra_data == NULL)
00619                 return 0;
00620 
00621         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00622         {
00623                 if (dfs->extra_data->mntput_vfsmount)
00624                 {
00625                         mntput(dfs->extra_data->vfsmount);
00626                         dfs->extra_data->mntput_vfsmount = 0;
00627                 }
00628         }
00629         #endif
00630 
00631         if (dfs->extra_data->free_page_buffer)
00632         {
00633                 free_page((unsigned long)dfs->extra_data->buffer);
00634                 dfs->extra_data->free_page_buffer = 0;
00635         }
00636 
00637         if (dfs->extra_data->dput_dentry)
00638         {
00639                 dput(dfs->extra_data->dentry);
00640                 dfs->extra_data->dput_dentry = 0;
00641         }
00642 
00643         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
00644         {
00645                 if (dfs->extra_data->path_release_nd)
00646                 {
00647                         path_release(&(dfs->extra_data->nd));
00648                         dfs->extra_data->path_release_nd = 0;
00649                 }
00650         }
00651         #endif
00652 
00653         return 0;
00654 }
00655 
00656 inline int xp_fill_file_struct(struct dazuko_file_struct *dfs)
00657 {
00658         struct dazuko_file_listnode     *listnode;
00659         int                             follow_symlinks = 0;
00660         int                             error = -1;
00661         int                             loopcount = 0;
00662         char                            *freeparentpath = NULL;
00663         char                            *parentpath = NULL;
00664         char                            *rawfilename = NULL;
00665         int                             i;
00666 
00667         if (dfs == NULL)
00668                 return error;
00669 
00670         /* check if filenames have already been filled in */
00671         if (dfs->aliases != NULL)
00672                 return 0;
00673 
00674         if (dfs->extra_data == NULL)
00675                 return error;
00676 
00677         /* make sure we can get an inode */
00678         while (1)
00679         {
00680                 loopcount++;
00681 
00682                 if (dfs->extra_data->user_filename != NULL)
00683                 {
00684                         if (!dazuko_get_filename_dentry(dfs->extra_data, follow_symlinks, dfs->extra_data->user_filename, 1))
00685                         {
00686                                 /* we will try to build a "fake" name from the parent directory */
00687 
00688                                 freeparentpath = getname(dfs->extra_data->user_filename);
00689                                 /* make sure it is a valid name */
00690                                 if (IS_ERR(freeparentpath))
00691                                 {
00692                                         freeparentpath = NULL;
00693                                         break;
00694                                 }
00695 
00696                                 parentpath = freeparentpath;
00697 
00698                                 i = dazuko_get_filename_length(parentpath);
00699                                 if (i == 0)
00700                                         break;
00701 
00702                                 while (i > 0)
00703                                 {
00704                                         if (parentpath[i] == '/')
00705                                         {
00706                                                 rawfilename = parentpath + i + 1;
00707                                                 parentpath[i] = 0;
00708                                                 break;
00709                                         }
00710 
00711                                         i--;
00712                                 }
00713                                 if (i == 0)
00714                                 {
00715                                         if (parentpath[i] == '/')
00716                                         {
00717                                                 rawfilename = parentpath + 1;
00718                                                 parentpath = "/";
00719                                         }
00720                                         else
00721                                         {
00722                                                 rawfilename = parentpath;
00723                                                 parentpath = ".";
00724                                         }
00725                                 }
00726 
00727                                 if (!dazuko_get_filename_dentry(dfs->extra_data, follow_symlinks, parentpath, 0))
00728                                 {
00729                                         putname(freeparentpath);
00730                                         freeparentpath = NULL;
00731                                         break;
00732                                 }
00733                         }
00734                 }
00735                 else
00736                 {
00737                         if (!dazuko_get_fd_dentry(dfs->extra_data))
00738                         {
00739                                 break;
00740                         }
00741                         else
00742                         {
00743                                 /* make sure we don't loop a 2nd time */
00744                                 loopcount++;
00745                         }
00746                 }
00747 
00748                 /* make sure we can get the full path */
00749                 if (!dazuko_get_full_filename(dfs->extra_data))
00750                         break;
00751 
00752                 if (freeparentpath != NULL)
00753                 {
00754                         /* we are working with a "fake" name */
00755 
00756                         parentpath = dfs->extra_data->full_filename;
00757                         i =  dazuko_get_filename_length(rawfilename);
00758 
00759                         dfs->extra_data->full_filename = (char *)xp_malloc(dfs->extra_data->full_filename_length + 1 + i + 1);
00760                         if (dfs->extra_data->full_filename == NULL)
00761                         {
00762                                 /* put things back how they were and get out */
00763                                 dfs->extra_data->full_filename = parentpath;
00764                                 break;
00765                         }
00766 
00767                         /* copy parent path */
00768                         memcpy(dfs->extra_data->full_filename, parentpath, dfs->extra_data->full_filename_length);
00769 
00770                         /* possibly copy "/" */
00771                         if (dfs->extra_data->full_filename[dfs->extra_data->full_filename_length - 1] != '/')
00772                         {
00773                                 dfs->extra_data->full_filename[dfs->extra_data->full_filename_length] = '/';
00774                                 dfs->extra_data->full_filename_length++;
00775                         }
00776 
00777                         /* copy filename */
00778                         memcpy(dfs->extra_data->full_filename + dfs->extra_data->full_filename_length, rawfilename, i + 1);
00779                         dfs->extra_data->full_filename_length += i;
00780 
00781                         /* free allocated parent path */
00782                         xp_free(parentpath);
00783                 }
00784                 else
00785                 {
00786                         dfs->file_p.size = dfs->extra_data->dentry->d_inode->i_size;
00787                         dfs->file_p.set_size = 1;
00788                         dfs->file_p.uid = dfs->extra_data->dentry->d_inode->i_uid;
00789                         dfs->file_p.set_uid = 1;
00790                         dfs->file_p.gid = dfs->extra_data->dentry->d_inode->i_gid;
00791                         dfs->file_p.set_gid = 1;
00792                         dfs->file_p.mode = dfs->extra_data->dentry->d_inode->i_mode;
00793                         dfs->file_p.set_mode = 1;
00794                         dfs->file_p.device_type = dfs->extra_data->dentry->d_inode->i_dev;
00795                         dfs->file_p.set_device_type = 1;
00796                 }
00797 
00798                 if (S_ISREG(dfs->extra_data->dentry->d_inode->i_mode))
00799                 {
00800                         dfs->file_p.type = DAZUKO_REGULAR;
00801                         dfs->file_p.set_type = 1;
00802                 }
00803                 else if (S_ISLNK(dfs->extra_data->dentry->d_inode->i_mode))
00804                 {
00805                         dfs->file_p.type = DAZUKO_LINK;
00806                         dfs->file_p.set_type = 1;
00807                 }
00808                 else if (S_ISDIR(dfs->extra_data->dentry->d_inode->i_mode))
00809                 {
00810                         dfs->file_p.type = DAZUKO_DIRECTORY;
00811                         dfs->file_p.set_type = 1;
00812                 }
00813 
00814                 listnode = (struct dazuko_file_listnode *)xp_malloc(sizeof(struct dazuko_file_listnode));
00815                 if (listnode == NULL)
00816                         break;
00817 
00818                 dazuko_bzero(listnode, sizeof(struct dazuko_file_listnode));
00819 
00820                 listnode->filename = dfs->extra_data->full_filename;
00821                 listnode->filename_length = dfs->extra_data->full_filename_length;  /* the string length */
00822 
00823                 dfs->extra_data->free_full_filename = 0;
00824                 dfs->extra_data->full_filename = NULL;
00825                 dfs->extra_data->full_filename_length = 0;
00826 
00827                 if (dfs->aliases == NULL)
00828                 {
00829                         listnode->next = dfs->aliases;
00830                         dfs->aliases = listnode;
00831                 }
00832                 else
00833                 {
00834                         listnode->next = dfs->aliases->next;
00835                         dfs->aliases->next = listnode;
00836                 }
00837 
00838                 /* we successfully got the file information */
00839                 error = 0;
00840 
00841                 if (!follow_symlinks && dfs->file_p.set_type && dfs->file_p.type == DAZUKO_LINK && loopcount < 2)
00842                 {
00843                         /* this is a link, we will grab the real path now */
00844 
00845                         follow_symlinks = 1;
00846 
00847                         /* clean up because we are going to fill it again */
00848                         dazuko_fill_file_struct_cleanup(dfs);
00849                 }
00850                 else
00851                 {
00852                         /* we've grabbed the real path (or we already have 2 paths), so we are done */
00853 
00854                         break;
00855                 }
00856         }
00857 
00858         if (freeparentpath != NULL)
00859                 putname(freeparentpath);
00860 
00861         dazuko_fill_file_struct_cleanup(dfs);
00862 
00863         return error;
00864 }
00865 
00866 static int dazuko_file_struct_cleanup(struct dazuko_file_struct **dfs)
00867 {
00868         struct dazuko_file_listnode     *cur;
00869 
00870         if (dfs == NULL)
00871                 return 0;
00872 
00873         if (*dfs == NULL)
00874                 return 0;
00875 
00876         while ((*dfs)->aliases != NULL)
00877         {
00878                 cur = (*dfs)->aliases;
00879                 (*dfs)->aliases = cur->next;
00880 
00881                 if (cur->filename != NULL)
00882                         xp_free(cur->filename);
00883 
00884                 xp_free(cur);
00885         }
00886 
00887         if ((*dfs)->extra_data != NULL)
00888                 xp_free((*dfs)->extra_data);
00889 
00890         xp_free(*dfs);
00891 
00892         *dfs = NULL;
00893 
00894         return 0;
00895 }
00896 
00897 
00898 /* daemon id */
00899 
00900 static inline int check_parent(struct task_struct *parent, struct task_struct *child)
00901 {
00902         struct task_struct      *ts = child;
00903 
00904         if (parent == NULL || child == NULL)
00905                 return -1;
00906 
00907         while (1)
00908         {
00909                 if (ts == parent)
00910                         return 0;
00911 
00912 #ifdef TASKSTRUCT_USES_PARENT
00913                 if (ts->parent == NULL)
00914                         break;
00915 
00916                 if (ts == ts->parent)
00917                         break;
00918 
00919                 ts = ts->parent;
00920 #else
00921                 if (ts->p_pptr == NULL)
00922                         break;
00923 
00924                 if (ts == ts->p_pptr)
00925                         break;
00926 
00927                 ts = ts->p_pptr;
00928 #endif
00929         }
00930 
00931         return -1;
00932 }
00933 
00934 inline int xp_id_compare(struct xp_daemon_id *id1, struct xp_daemon_id *id2, int check_related)
00935 {
00936         if (id1 == NULL || id2 == NULL)
00937                 return DAZUKO_DIFFERENT;
00938 
00939         /* if file's are available and they match,
00940          * then we say that the id's match
00941          * ("file" is only used to unregister daemons and
00942          * here we allow other processes to do this)
00943          * Note: this is a Linux-only "hack" */
00944         if (id1->file != NULL && id1->file == id2->file)
00945                 return DAZUKO_SAME;
00946 
00947         if (id1->pid == id2->pid && id1->current_p == id2->current_p && id1->files == id2->files)
00948                 return DAZUKO_SAME;
00949 
00950         if (check_related)
00951         {
00952                 if (check_parent(id1->current_p, id2->current_p) == 0)
00953                 {
00954                         return DAZUKO_CHILD;
00955                 }
00956                 else if (id1->pid == id2->pid || id1->current_p == id2->current_p || id1->files == id2->files)
00957                 {
00958                         return DAZUKO_SUSPICIOUS;
00959                 }
00960         }
00961 
00962         return DAZUKO_DIFFERENT;
00963 }
00964 
00965 inline int xp_id_free(struct xp_daemon_id *id)
00966 {
00967         xp_free(id);
00968 
00969         return 0;
00970 }
00971 
00972 inline struct xp_daemon_id* xp_id_copy(struct xp_daemon_id *id)
00973 {
00974         struct xp_daemon_id     *ptr;
00975 
00976         if (id == NULL)
00977                 return NULL;
00978 
00979         ptr = (struct xp_daemon_id *)xp_malloc(sizeof(struct xp_daemon_id));
00980 
00981         if (ptr != NULL)
00982         {
00983                 ptr->pid = id->pid;
00984                 ptr->file = id->file;
00985                 ptr->current_p = id->current_p;
00986                 ptr->files = id->files;
00987         }
00988 
00989         return ptr;
00990 }
00991 
00992 
00993 /* event */
00994 
00995 int xp_set_event_properties(struct event_properties *event_p, struct xp_daemon_id *xp_id)
00996 {
00997         event_p->pid = xp_id->pid;
00998         event_p->set_pid = 1;
00999 
01000         return 0;
01001 }
01002 
01003 
01004 /* cache settings */
01005 
01006 int xp_init_cache(unsigned long ttl)
01007 {
01008         return -1;
01009 }
01010 
01011 
01012 /* system calls */
01013 
01014 #if defined(ON_OPEN_SUPPORT)
01015 asmlinkage long linux_dazuko_sys_open(const char *filename, int flags, int mode)
01016 {
01017         /* The kernel wants to open the given filename
01018          * with the given flags and mode. The dazuko_file_struct
01019          * is used to handle the tricky job of cleaning
01020          * up the many pieces of memory that may or may
01021          * not be allocated. */
01022 
01023         struct dazuko_file_struct       *dfs = NULL;
01024         int                             error = 0;
01025         int                             fd;
01026         int                             check_error = 0;
01027         struct event_properties         event_p;
01028         struct xp_daemon_id             xp_id;
01029 
01030         xp_id.pid = current->pid;
01031         xp_id.file = NULL;
01032         xp_id.current_p = current;
01033         xp_id.files = current->files;
01034 
01035         check_error = dazuko_check_access(DAZUKO_ON_OPEN, 1, &xp_id, NULL);
01036 
01037         if (!check_error)
01038         {
01039                 dazuko_bzero(&event_p, sizeof(event_p));
01040                 event_p.flags = flags;
01041                 event_p.set_flags = 1;
01042                 event_p.mode = mode;
01043                 event_p.set_mode = 1;
01044                 event_p.pid = current->pid;
01045                 event_p.set_pid = 1;
01046                 event_p.uid = current->uid;
01047                 event_p.set_uid = 1;
01048 
01049                 dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01050                 if (dfs != NULL)
01051                 {
01052                         dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01053 
01054                         dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01055                         if (dfs->extra_data != NULL)
01056                         {
01057                                 dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01058 
01059                                 dfs->extra_data->user_filename = filename;
01060 
01061                                 error = dazuko_process_access(DAZUKO_ON_OPEN, dfs, &event_p, NULL);
01062 
01063                                 dazuko_file_struct_cleanup(&dfs);
01064                         }
01065                         else
01066                         {
01067                                 xp_free(dfs);
01068                                 dfs = NULL;
01069                         }
01070                 }
01071         }
01072 
01073         if (error)
01074         {
01075                 /* access should be blocked */
01076 
01077                 fd = -1;
01078         }
01079         else
01080         {
01081                 /* call the standard open function */
01082                 fd = original_sys_open(filename, flags, mode);
01083         }
01084 
01085         return fd;
01086 }
01087 
01088 asmlinkage long linux_dazuko_sys_dup(unsigned int filedes)
01089 {
01090         struct dazuko_file_struct       *dfs = NULL;
01091         struct event_properties         event_p;
01092         struct xp_daemon_id             xp_id;
01093         int                             error = 0;
01094         int                             check_error = 0;
01095 
01096         xp_id.pid = current->pid;
01097         xp_id.file = NULL;
01098         xp_id.current_p = current;
01099         xp_id.files = current->files;
01100 
01101         check_error = dazuko_check_access(DAZUKO_ON_OPEN, 1, &xp_id, NULL);
01102 
01103         if (!check_error)
01104         {
01105                 dazuko_bzero(&event_p, sizeof(event_p));
01106 
01107                 if (filedes >= 0 && filedes < current->files->max_fds)
01108                 {
01109                         event_p.pid = current->pid;
01110                         event_p.set_pid = 1;
01111                         event_p.uid = current->uid;
01112                         event_p.set_uid = 1;
01113 
01114                         dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01115                         if (dfs != NULL)
01116                         {
01117                                 dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01118 
01119                                 dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01120                                 if (dfs->extra_data != NULL)
01121                                 {
01122                                         dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01123 
01124                                         dfs->extra_data->fd = filedes;
01125 
01126                                         error = dazuko_process_access(DAZUKO_ON_OPEN, dfs, &event_p, NULL);
01127 
01128                                         dazuko_file_struct_cleanup(&dfs);
01129                                 }
01130                                 else
01131                                 {
01132                                         xp_free(dfs);
01133                                         dfs = NULL;
01134                                 }
01135                         }
01136                 }
01137                 else
01138                 {
01139                         check_error = -1;
01140                 }
01141         }
01142 
01143         if (error)
01144         {
01145                 /* access should be blocked */
01146 
01147                 error = -EPERM;
01148         }
01149         else
01150         {
01151                 /* call the standard open function */
01152                 error = original_sys_dup(filedes);
01153         }
01154 
01155         return error;
01156 }
01157 #endif
01158 
01159 #if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01160 asmlinkage long linux_dazuko_sys_dup2(unsigned int oldfd, unsigned int newfd)
01161 {
01162         struct dazuko_file_struct       *dfs = NULL;
01163         struct event_properties         open_event_p;
01164         struct xp_daemon_id             xp_id;
01165         int                             error = 0;
01166         int                             check_error = 0;
01167 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01168         struct event_properties         close_event_p;
01169         int                             will_close_newfd = 0;
01170 #endif
01171 
01172         xp_id.pid = current->pid;
01173         xp_id.file = NULL;
01174         xp_id.current_p = current;
01175         xp_id.files = current->files;
01176 
01177         check_error = dazuko_check_access(DAZUKO_ON_OPEN, 1, &xp_id, NULL);
01178 
01179         if (!check_error)
01180         {
01181                 dazuko_bzero(&open_event_p, sizeof(open_event_p));
01182 
01183                 if (oldfd != newfd && oldfd >= 0 && oldfd < current->files->max_fds)
01184                 {
01185                         open_event_p.pid = current->pid;
01186                         open_event_p.set_pid = 1;
01187                         open_event_p.uid = current->uid;
01188                         open_event_p.set_uid = 1;
01189 
01190                         dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01191                         if (dfs != NULL)
01192                         {
01193                                 dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01194 
01195                                 dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01196                                 if (dfs->extra_data != NULL)
01197                                 {
01198                                         dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01199 
01200                                         dfs->extra_data->fd = oldfd;
01201 
01202                                         error = dazuko_process_access(DAZUKO_ON_OPEN, dfs, &open_event_p, NULL);
01203 
01204                                         dazuko_file_struct_cleanup(&dfs);
01205                                 }
01206                                 else
01207                                 {
01208                                         xp_free(dfs);
01209                                         dfs = NULL;
01210                                 }
01211                         }
01212                 }
01213                 else
01214                 {
01215                         check_error = -1;
01216                 }
01217         }
01218 
01219         if (error)
01220         {
01221                 /* access should be blocked */
01222 
01223                 error = -EPERM;
01224         }
01225         else
01226         {
01227                 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01228                 if (newfd >= 0 && newfd < current->files->max_fds)
01229                 {
01230                         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01231                         {
01232                                 read_lock(&current->files->file_lock);
01233                         }
01234                         #endif
01235 
01236                         if (current->files->fd[newfd] != NULL)
01237                         {
01238                                 will_close_newfd = 1;
01239                         }
01240 
01241                         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01242                         {
01243                                 read_unlock(&current->files->file_lock);
01244                         }
01245                         #endif
01246                 }
01247                 #endif
01248 
01249                 /* call the standard open function */
01250                 error = original_sys_dup2(oldfd, newfd);
01251 
01252                 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01253                 {
01254                         if (!check_error)
01255                         {
01256                                 if (error >= 0 && will_close_newfd)
01257                                 {
01258                                         dazuko_bzero(&close_event_p, sizeof(close_event_p));
01259 
01260                                         close_event_p.pid = current->pid;
01261                                         close_event_p.set_pid = 1;
01262                                         close_event_p.uid = current->uid;
01263                                         close_event_p.set_uid = 1;
01264 
01265                                         dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01266                                         if (dfs != NULL)
01267                                         {
01268                                                 dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01269 
01270                                                 dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01271                                                 if (dfs->extra_data != NULL)
01272                                                 {
01273                                                         dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01274 
01275                                                         dfs->extra_data->fd = newfd;
01276 
01277                                                         dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &close_event_p, NULL);
01278 
01279                                                         dazuko_file_struct_cleanup(&dfs);
01280                                                 }
01281                                                 else
01282                                                 {
01283                                                         xp_free(dfs);
01284                                                         dfs = NULL;
01285                                                 }
01286                                         }
01287                                 }
01288                         }
01289                 }
01290                 #endif
01291         }
01292 
01293         return error;
01294 }
01295 #endif
01296 
01297 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01298 asmlinkage long linux_dazuko_sys_close(unsigned int fd)
01299 {
01300         /* The kernel wants to close the given file
01301          * descriptor. */
01302 
01303         struct dazuko_file_struct       *dfs = NULL;
01304         int                             error = 0;
01305         int                             check_error = 0;
01306         struct event_properties         event_p;
01307         struct xp_daemon_id             xp_id;
01308 
01309         xp_id.pid = current->pid;
01310         xp_id.file = NULL;
01311         xp_id.current_p = current;
01312         xp_id.files = current->files;
01313 
01314         check_error = dazuko_check_access(DAZUKO_ON_CLOSE, 1, &xp_id, NULL);
01315 
01316         if (!check_error && fd >= 0 && fd < current->files->max_fds)
01317         {
01318                 dazuko_bzero(&event_p, sizeof(event_p));
01319 
01320                 event_p.pid = current->pid;
01321                 event_p.set_pid = 1;
01322                 event_p.uid = current->uid;
01323                 event_p.set_uid = 1;
01324 
01325                 dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01326                 if (dfs != NULL)
01327                 {
01328                         dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01329 
01330                         dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01331                         if (dfs->extra_data != NULL)
01332                         {
01333                                 dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01334 
01335                                 dfs->extra_data->fd = fd;
01336 
01337                                 check_error = xp_fill_file_struct(dfs);
01338                         }
01339                         else
01340                         {
01341                                 xp_free(dfs);
01342                                 dfs = NULL;
01343                         }
01344                 }
01345         }
01346 
01347         error = original_sys_close(fd);
01348 
01349         if (dfs != NULL)
01350         {
01351                 if (!check_error)
01352                 {
01353                         dazuko_process_access(DAZUKO_ON_CLOSE, dfs, &event_p, NULL);
01354                 }
01355 
01356                 dazuko_file_struct_cleanup(&dfs);
01357         }
01358 
01359         return error;
01360 }
01361 #endif
01362 
01363 #ifdef ON_EXEC_SUPPORT
01364 asmlinkage int linux_dazuko_sys_execve(struct pt_regs regs)
01365 {
01366         /* The kernel wants to execute the given file.
01367          * Because the given structure contains stack
01368          * address information, we can't simply call
01369          * the default standard execve. Instead we
01370          * have to manually inline the standard execve
01371          * call. */
01372 
01373         struct dazuko_file_struct       *dfs = NULL;
01374         char                            *filename;
01375         int                             error = 0;
01376         int                             check_error = 0;
01377         struct event_properties         event_p;
01378         struct xp_daemon_id             xp_id;
01379         struct slot_list                *sl = NULL;
01380 
01381         xp_id.pid = current->pid;
01382         xp_id.file = NULL;
01383         xp_id.current_p = current;
01384         xp_id.files = current->files;
01385 
01386         check_error = dazuko_check_access(DAZUKO_ON_EXEC, 0, &xp_id, &sl);
01387 
01388         if (!check_error)
01389         {
01390                 dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01391                 if (dfs)
01392                 {
01393                         dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01394 
01395                         dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01396                         if (dfs->extra_data != NULL)
01397                         {
01398                                 dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01399 
01400                                 dfs->extra_data->user_filename = (char *)regs.ebx;
01401 
01402                                 dazuko_bzero(&event_p, sizeof(event_p));
01403                                 event_p.pid = current->pid;
01404                                 event_p.set_pid = 1;
01405                                 event_p.uid = current->uid;
01406                                 event_p.set_uid = 1;
01407 
01408                                 error = dazuko_process_access(DAZUKO_ON_EXEC, dfs, &event_p, sl);
01409 
01410                                 dazuko_file_struct_cleanup(&dfs);
01411                         }
01412                         else
01413                         {
01414                                 xp_free(dfs);
01415                                 dfs = NULL;
01416                         }
01417                 }
01418         }
01419 
01420         if (error)
01421         {
01422                 return error;
01423         }
01424 
01425         /* call the standard execve function */
01426 
01427         /* We cannot simply call the original version of execvc
01428          * because the parameter contains stack information and
01429          * the call will push the execvc call onto a new stack
01430          * level and seg fault. :( */
01431 
01432         /* The following code only works on i386 machines.
01433          * It is directly copied from Linux in the file:
01434          * arch/i386/kernel/process.c */
01435 
01436         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01437         {
01438                 filename = getname((char *) regs.ebx);
01439                 error = PTR_ERR(filename);
01440                 if (IS_ERR(filename))
01441                 {
01442                         filename = NULL;
01443                         goto out;
01444                 }
01445                 error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
01446                 if (error == 0)
01447                         current->ptrace &= ~PT_DTRACE;
01448                 putname(filename);
01449 out:
01450                 return error;
01451         }
01452         #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,20)
01453         {
01454                 #ifdef __SMP__
01455                         lock_kernel();
01456                 #endif
01457                 filename = getname((char *) regs.ebx);
01458                 error = PTR_ERR(filename);
01459                 if (IS_ERR(filename))
01460                 {
01461                         filename = NULL;
01462                         goto out;
01463                 }
01464                 error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
01465                 if (error == 0)
01466                         current->ptrace &= ~PT_DTRACE;
01467                 putname(filename);
01468 out:
01469                 #ifdef __SMP__
01470                         unlock_kernel();
01471                 #endif
01472                 return error;
01473         }
01474         #else
01475         {
01476                 #ifdef __SMP__
01477                         lock_kernel();
01478                 #endif
01479                 filename = getname((char *) regs.ebx);
01480                 error = PTR_ERR(filename);
01481                 if (IS_ERR(filename))
01482                 {
01483                         filename = NULL;
01484                         goto out;
01485                 }
01486                 error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
01487                 if (error == 0)
01488                         current->flags &= ~PF_DTRACE;
01489                 putname(filename);
01490 out:
01491                 #ifdef __SMP__
01492                         unlock_kernel();
01493                 #endif
01494                 return error;
01495         }
01496         #endif
01497 }
01498 #endif
01499 
01500 static inline int linux_dazuko_sys_generic(int event, const char *user_pathname, int daemon_is_allowed)
01501 {
01502         struct dazuko_file_struct       *dfs = NULL;
01503         int                             error = 0;
01504         int                             check_error = 0;
01505         struct event_properties         event_p;
01506         struct xp_daemon_id             xp_id;
01507         struct slot_list                *sl = NULL;
01508 
01509         xp_id.pid = current->pid;
01510         xp_id.file = NULL;
01511         xp_id.current_p = current;
01512         xp_id.files = current->files;
01513 
01514         check_error = dazuko_check_access(event, daemon_is_allowed, &xp_id, &sl);
01515 
01516         if (!check_error)
01517         {
01518                 dfs = (struct dazuko_file_struct *)xp_malloc(sizeof(struct dazuko_file_struct));
01519                 if (dfs)
01520                 {
01521                         dazuko_bzero(dfs, sizeof(struct dazuko_file_struct));
01522 
01523                         dfs->extra_data = (struct xp_file_struct *)xp_malloc(sizeof(struct xp_file_struct));
01524                         if (dfs->extra_data != NULL)
01525                         {
01526                                 dazuko_bzero(dfs->extra_data, sizeof(struct xp_file_struct));
01527 
01528                                 dfs->extra_data->user_filename = user_pathname;
01529 
01530                                 dazuko_bzero(&event_p, sizeof(event_p));
01531                                 event_p.pid = current->pid;
01532                                 event_p.set_pid = 1;
01533                                 event_p.uid = current->uid;
01534                                 event_p.set_uid = 1;
01535 
01536                                 error = dazuko_process_access(event, dfs, &event_p, sl);
01537 
01538                                 dazuko_file_struct_cleanup(&dfs);
01539                         }
01540                         else
01541                         {
01542                                 xp_free(dfs);
01543                                 dfs = NULL;
01544                         }
01545                 }
01546         }
01547 
01548         return error;
01549 }
01550 
01551 #ifdef ON_UNLINK_SUPPORT
01552 asmlinkage long linux_dazuko_sys_unlink(const char *pathname)
01553 {
01554         int     error;
01555 
01556         error = linux_dazuko_sys_generic(DAZUKO_ON_UNLINK, pathname, 1);
01557 
01558         if (error)
01559                 return error;
01560 
01561         return original_sys_unlink(pathname);
01562 }
01563 #endif
01564 
01565 #ifdef ON_RMDIR_SUPPORT
01566 asmlinkage long linux_dazuko_sys_rmdir(const char *pathname)
01567 {
01568         int     error;
01569 
01570         error = linux_dazuko_sys_generic(DAZUKO_ON_RMDIR, pathname, 1);
01571 
01572         if (error)
01573                 return error;
01574 
01575         return original_sys_rmdir(pathname);
01576 }
01577 #endif
01578 
01579 
01580 /* system hook */
01581 
01582 #ifdef HIDDEN_SCT
01583 static void** dazuko_get_sct()
01584 {
01585         unsigned long   ptr;
01586         extern int      loops_per_jiffy;
01587         unsigned long   *p;
01588 
01589         for (ptr=(unsigned long)&loops_per_jiffy ; ptr<(unsigned long)&boot_cpu_data ; ptr+=sizeof(void *))
01590         {
01591                 p = (unsigned long *)ptr;
01592                 if (p[6] == (unsigned long)sys_close)
01593                 {
01594                         return (void **)p;
01595                 }
01596         }
01597 
01598         return NULL;
01599 }
01600 #endif
01601 
01602 #define DAZUKO_HOOK(syscall_func) do \
01603 { \
01604         original_sys_##syscall_func = sys_call_table[__NR_##syscall_func]; \
01605         sys_call_table[__NR_##syscall_func] = linux_dazuko_sys_##syscall_func; \
01606         DPRINT(("dazuko: hooked sys_" #syscall_func "\n")); \
01607 } \
01608 while (0)
01609 
01610 inline int xp_sys_hook()
01611 {
01612         /* Called insmod when inserting the module. */
01613 
01614 #ifdef HIDDEN_SCT
01615         sys_call_table = dazuko_get_sct();
01616         if (sys_call_table == NULL)
01617         {
01618                 xp_print("dazuko: panic (sys_call_table == NULL)\n");
01619                 return -1;
01620         }
01621 #endif
01622 
01623         /* Make sure we have a valid task_struct. */
01624 
01625         if (current == NULL)
01626         {
01627                 xp_print("dazuko: panic (current == NULL)\n");
01628                 return -1;
01629         }
01630         if (current->fs == NULL)
01631         {
01632                 xp_print("dazuko: panic (current->fs == NULL)\n");
01633                 return -1;
01634         }
01635         if (current->fs->root == NULL)
01636         {
01637                 xp_print("dazuko: panic (current->fs->root == NULL)\n");
01638                 return -1;
01639         }
01640         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01641         {
01642                 if (current->fs->rootmnt == NULL)
01643                 {
01644                         xp_print("dazuko: panic (current->fs->rootmnt == NULL)\n");
01645                         return -1;
01646                 }
01647         }
01648         #endif
01649 
01650         /* register the dazuko device */
01651 #ifdef DEVFS_SUPPORT
01652         dev_major = devfs_register_chrdev(0, DEVICE_NAME, &fops);
01653         devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
01654                 dev_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
01655                 &fops, NULL);
01656 #else
01657         dev_major = register_chrdev(DAZUKO_DM, DEVICE_NAME, &fops);
01658 #endif
01659         if (dev_major < 0)
01660         {
01661                 xp_print("dazuko: unable to register device chrdev, err=%d\n", dev_major);
01662                 return dev_major;
01663         }
01664 
01665         /* Grab the current root. This is assumed to be the real.
01666          * If it is not the real root, we could have problems
01667          * looking up filenames. */
01668 
01669         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01670         {
01671                 read_lock(&current->fs->lock);
01672                 orig_rootmnt = current->fs->rootmnt;
01673         }
01674         #endif
01675 
01676         orig_root = current->fs->root;
01677 
01678         #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01679                 read_unlock(&current->fs->lock);
01680         #endif
01681 
01682         /* do a file syncronization on all devices (IMPORTANT!) and replace system calls */
01683         #ifdef __SMP__
01684                 lock_kernel();
01685         #endif
01686 
01687         fsync_dev(0);
01688 
01689 #if defined(ON_OPEN_SUPPORT)
01690         DAZUKO_HOOK(open);
01691         DAZUKO_HOOK(dup);
01692 #endif
01693 #if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01694         DAZUKO_HOOK(dup2);
01695 #endif
01696         
01697 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01698         DAZUKO_HOOK(close);
01699 #endif
01700 
01701 #ifdef ON_EXEC_SUPPORT
01702         DAZUKO_HOOK(execve);
01703 #endif
01704 
01705 #ifdef ON_UNLINK_SUPPORT
01706         DAZUKO_HOOK(unlink);
01707 #endif
01708 
01709 #ifdef ON_RMDIR_SUPPORT
01710         DAZUKO_HOOK(rmdir);
01711 #endif
01712 
01713         #ifdef __SMP__
01714                 unlock_kernel();
01715         #endif
01716         /* done syncing and replacing */
01717 
01718         /* initialization complete */
01719 
01720         return 0;
01721 }
01722 
01723 #define DAZUKO_UNHOOK(syscall_func) do \
01724 { \
01725         if (sys_call_table[__NR_##syscall_func] != linux_dazuko_sys_##syscall_func) \
01726                 xp_print("dazuko: " #syscall_func " system call has been changed (system may be left in an unstable state!)\n"); \
01727         sys_call_table[__NR_##syscall_func] = original_sys_##syscall_func; \
01728         DPRINT(("dazuko: unhooked sys_" #syscall_func "\n")); \
01729 } \
01730 while (0)
01731 
01732 inline int xp_sys_unhook()
01733 {
01734         /* Called by rmmod when removing the module. */
01735 
01736         int     error;
01737 
01738         /* do a file syncronization on all devices (IMPORTANT!) and replace system calls */
01739         #ifdef __SMP__
01740                 lock_kernel();
01741         #endif
01742 
01743         fsync_dev(0);
01744 
01745 #if defined(ON_OPEN_SUPPORT)
01746         DAZUKO_UNHOOK(open);
01747         DAZUKO_UNHOOK(dup);
01748 #endif
01749 #if defined(ON_OPEN_SUPPORT) || defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01750         DAZUKO_UNHOOK(dup2);
01751 #endif
01752 
01753 #if defined(ON_CLOSE_SUPPORT) || defined(ON_CLOSE_MODIFIED_SUPPORT)
01754         DAZUKO_UNHOOK(close);
01755 #endif
01756 
01757 #ifdef ON_EXEC_SUPPORT
01758         DAZUKO_UNHOOK(execve);
01759 #endif
01760 
01761 #ifdef ON_UNLINK_SUPPORT
01762         DAZUKO_UNHOOK(unlink);
01763 #endif
01764 
01765 #ifdef ON_RMDIR_SUPPORT
01766         DAZUKO_UNHOOK(rmdir);
01767 #endif
01768 
01769         #ifdef __SMP__
01770                 unlock_kernel();
01771         #endif
01772         /* done syncing and replacing */
01773 
01774 #ifdef DEVFS_SUPPORT
01775         error = devfs_unregister_chrdev(dev_major, DEVICE_NAME);
01776         devfs_unregister(devfs_find_handle(NULL, DEVICE_NAME, dev_major, 0, DEVFS_SPECIAL_CHR, 0));
01777 #else
01778         error = unregister_chrdev(dev_major, DEVICE_NAME);
01779 #endif
01780         if (error < 0)
01781         {
01782                 xp_print("dazuko: error unregistering chrdev, err=%d\n", error);
01783         }
01784 
01785         return 0;
01786 }
01787 
01788 
01789 /* output */
01790 
01791 int xp_print(const char *fmt, ...)
01792 {
01793         va_list args;
01794         char *p;
01795         size_t size = 1024;
01796 
01797         p = (char *)xp_malloc(size);
01798         if (!p)
01799                 return -1;
01800 
01801         va_start(args, fmt);
01802         dazuko_vsnprintf(p, size-1, fmt, args);
01803         va_end(args);
01804 
01805         p[size-1] = 0;
01806 
01807         printk(p);
01808 
01809         xp_free(p);
01810 
01811         return 0;
01812 }
01813 
01814 
01815 /* ioctl's */
01816 
01817 int linux_dazuko_device_open(struct inode *inode, struct file *file)
01818 {
01819         DPRINT(("dazuko: linux_dazuko_device_open() [%d]\n", current->pid));
01820 
01821         return 0;
01822 }
01823 
01824 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
01825 int linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos)
01826 #else
01827 ssize_t linux_dazuko_device_read(struct file *file, char *buffer, size_t length, loff_t *pos)
01828 #endif
01829 {
01830         /* Reading from the dazuko device simply
01831          * returns the device number. This is to
01832          * help out the daemon. */
01833 
01834         char    tmp[20];
01835         size_t  dev_major_len;
01836 
01837         DPRINT(("dazuko: linux_dazuko_device_read() [%d]\n", current->pid));
01838 
01839         /* only one read is allowed */
01840         if (*pos != 0)
01841                 return 0;
01842 
01843         if (dev_major < 0)
01844                 return -ENODEV;
01845 
01846         /* print dev_major to a string
01847          * and get length (with terminator) */
01848         dazuko_bzero(tmp, sizeof(tmp));
01849 
01850         dev_major_len = dazuko_snprintf(tmp, sizeof(tmp), "%d", dev_major) + 1;
01851 
01852         if (tmp[sizeof(tmp)-1] != 0)
01853         {
01854                 xp_print("dazuko: failing device_read, device number overflow for dameon %d (dev_major=%d)\n", current->pid, dev_major);
01855                 return -EFAULT;
01856         }
01857 
01858         if (length < dev_major_len)
01859                 return -EINVAL;
01860 
01861         /* copy dev_major string to userspace */
01862         if (xp_copyout(tmp, buffer, dev_major_len) != 0)
01863                 return -EFAULT;
01864 
01865         *pos = dev_major_len;
01866 
01867         return dev_major_len;
01868 }
01869 
01870 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
01871 int linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos)
01872 {
01873         /* multiple device_write entries are not allowed
01874          * with older kernels, so we force compat1 mode */
01875 
01876         return length;
01877 }
01878 #else
01879 ssize_t linux_dazuko_device_write(struct file *file, const char *buffer, size_t length, loff_t *pos)
01880 {
01881         struct xp_daemon_id     xp_id;
01882         char                    tmpbuffer[32];
01883         int                     size;
01884 
01885         size = length;
01886         if (length >= sizeof(tmpbuffer))
01887                 size = sizeof(tmpbuffer) -1;
01888 
01889         /* copy request pointer string to kernelspace */
01890         if (xp_copyin(buffer, tmpbuffer, size) != 0)
01891                 return -EFAULT;
01892 
01893         tmpbuffer[size] = 0;
01894 
01895         xp_id.pid = current->pid;
01896         xp_id.file = file;
01897         xp_id.current_p = current;
01898         xp_id.files = current->files;
01899 
01900         if (dazuko_handle_user_request(tmpbuffer, &xp_id) == 0)
01901                 return length;
01902         else
01903                 return -EINTR;
01904 }
01905 #endif
01906 
01907 int linux_dazuko_device_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long param)
01908 {
01909         /* A daemon uses this function to interact with
01910          * the kernel. A daemon can set scanning parameters,
01911          * give scanning response, and get filenames to scan. */
01912 
01913         struct xp_daemon_id     xp_id;
01914         int                     error = 0;
01915 
01916         if (param == 0)
01917         {
01918                 xp_print("dazuko: error: linux_dazuko_device_ioctl(..., 0)\n");
01919                 return -EFAULT;
01920         }
01921 
01922         xp_id.pid = current->pid;
01923         xp_id.file = file;
01924         xp_id.current_p = current;
01925         xp_id.files = current->files;
01926 
01927         error = dazuko_handle_user_request_compat1((void *)param, _IOC_NR(cmd), &xp_id);
01928 
01929         if (error != 0)
01930         {
01931                 /* general error occurred */
01932 
01933                 return -EPERM;
01934         }
01935 
01936         return error;
01937 }
01938 
01939 int linux_dazuko_device_release(struct inode *inode, struct file *file)
01940 {
01941         struct xp_daemon_id     xp_id;
01942 
01943         DPRINT(("dazuko: dazuko_device_release() [%d]\n", current->pid));
01944 
01945         xp_id.pid = current->pid;
01946         xp_id.file = file;
01947         xp_id.current_p = current;
01948         xp_id.files = current->files;
01949 
01950         return dazuko_unregister_daemon(&xp_id);
01951 }
01952 
01953 
01954 /* init/exit */
01955 
01956 int __init linux_dazuko_init(void)
01957 {
01958         return dazuko_init();
01959 }
01960 
01961 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
01962 void __exit linux_dazuko_exit(void)
01963 #else
01964 void linux_dazuko_exit(void)
01965 #endif
01966 {
01967         dazuko_exit();
01968 }
01969 
01970 
01971 #ifdef MODULE
01972         
01973 MODULE_AUTHOR("H+BEDV Datentechnik GmbH <linux_support@antivir.de>");
01974 MODULE_DESCRIPTION("allow 3rd-party file access control");
01975 #ifdef MODULE_LICENSE
01976 MODULE_LICENSE("GPL");
01977 #else
01978 static const char __module_license[] __attribute__((section(".modinfo"))) = "license=GPL";
01979 #endif   
01980 
01981 int init_module(void)
01982 {
01983         return linux_dazuko_init();
01984 }
01985 
01986 void cleanup_module(void)
01987 {
01988         linux_dazuko_exit();
01989 }
01990                 
01991 EXPORT_NO_SYMBOLS;
01992 
01993 #else
01994 
01995 module_init(linux_dazuko_init);
01996 module_exit(linux_dazuko_exit);
01997 /* module_init(int linux_dazuko_init(void)); */
01998 /* module_exit(void linux_dazuko_exit(void)); */
01999 
02000 #endif

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