opt
/
kaspersky
/
kav4fs
/
src
/
kernel
/
module.freebsd
➕ New
📤 Upload
✎ Editing:
interface_monitor.c
← Back
/* * This source file is a part of a Kaspersky Antivirus Monitor. * Copyright (C) Kaspersky Lab, 1997-2010 * See License.txt for details * */ #include "module.h" #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 static int monitor_open (dev_t dev, int oflags, int devtype, struct proc *p); static int monitor_close (dev_t dev, int fflag, int devtype, struct proc *p); static int monitor_read (dev_t dev, struct uio *uio, int ioflag); static int monitor_write (dev_t dev, struct uio *uio, int ioflag); static int monitor_poll (dev_t dev, int events, struct proc *thr); static int monitor_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag,struct proc *p); #else #if __FreeBSD_version >= 500003 static int monitor_open (struct cdev * dev, int oflags, int devtype, struct thread *thr); static int monitor_close (struct cdev * dev, int fflag, int devtype, struct thread *thr); static int monitor_read (struct cdev * dev, struct uio *uio, int ioflag); static int monitor_write (struct cdev * dev, struct uio *uio, int ioflag); static int monitor_poll (struct cdev * dev, int events, struct thread *thr); static int monitor_ioctl (struct cdev * dev, u_long cmd, caddr_t data, int flag,struct thread *thr); #else static int monitor_open (dev_t dev, int oflags, int devtype, struct thread *thr); static int monitor_close (dev_t dev, int fflag, int devtype, struct thread *thr); static int monitor_read (dev_t dev, struct uio *uio, int ioflag); static int monitor_write (dev_t dev, struct uio *uio, int ioflag); static int monitor_poll (dev_t dev, int events, struct thread *thr); static int monitor_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag,struct thread *thr); #endif #endif struct vnode *orig_rootmnt = NULL; static lock_declare(monitor_lock); volatile int monitor_started; volatile int monitor_opened; static TransportBuffer send_buff; static TransportBuffer recv_buff; static lock_declare(send_buff_lock); static lock_declare(recv_buff_lock); static wait_queue_head_t queue_empty_waitq; static struct selinfo queue_empty_select; static void * my_alloc(size_t size) { return MEM_ALLOC(size); } static void my_free(void * ptr) { return MEM_FREE(ptr); } static void file_checked(void* ctx, const CheckFileResultInfoData * data); static void monitor_shutdown(void * ctx); static ProtocolCallbacks m_callbacks = { check_file :NULL, notify_file :NULL, samba_connect :NULL, check_file_result :file_checked, shutdown :monitor_shutdown }; static ProtocolAllocator m_alloc = { alloc: my_alloc, free: my_free }; #if defined (__FreeBSD_version) && __FreeBSD_version >= 500000 struct cdevsw dev_kavmonitor = { #if __FreeBSD_version >= 500003 .d_version = D_VERSION, .d_flags = 0, #endif .d_open = monitor_open, .d_close = monitor_close, .d_read = monitor_read, .d_write = monitor_write, .d_ioctl = monitor_ioctl, .d_poll = monitor_poll, #if __FreeBSD_version < 500003 .d_mmap = nommap, .d_strategy = nostrategy, .d_kqfilter = NULL, .d_dump = nodump, #endif .d_name = "KAV4FS_OAS", #if defined (__FreeBSD_version) && __FreeBSD_version < 600000 .d_maj = KAVMON_DEVICE_MAJOR, #endif #if __FreeBSD_version < 501000 .d_psize = nopsize, .d_flags = 0 #endif }; #elif defined (__FreeBSD_version) && __FreeBSD_version >= 400006 struct cdevsw dev_kavmonitor = { monitor_open, monitor_close, monitor_read, monitor_write, monitor_ioctl, monitor_poll, nommap, nostrategy, "KAV4FS_OAS", KAVMON_DEVICE_MAJOR, nodump, nopsize, D_TTY, -1 }; #else struct cdevsw dev_kavmonitor = { monitor_open, monitor_close, monitor_read, monitor_write, monitor_ioctl, nostop, nullreset, nodevtotty, monitor_poll, nommap, NULL, "KAV4FS_OAS", NULL, -1 }; #endif int Monitor_module_init (void) { monitor_started = 0; monitor_opened = 0; ProtocolCallbacksInit(&m_callbacks); SetProtocolAllocator(&m_alloc); #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 queue_empty_select.si_flags = 0; queue_empty_select.si_pid = 0; #endif lock_init(&monitor_lock,"kavmonitor module lock"); lock_init(&send_buff_lock,"kavmonitor send buffer lock"); lock_init(&recv_buff_lock,"kavmonitor receive buffer lock"); return 0; } void Monitor_module_send_data(const PackedBuffer * buff) { write_lock(&send_buff_lock); TransportBufferAddPacket(&send_buff, buff); write_unlock(&send_buff_lock); selwakeup (&queue_empty_select); /* Wake up all select() calls */ wake_up(&queue_empty_waitq); } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 static int monitor_module_stop(struct proc * thr) #else static int monitor_module_stop(struct thread * thr) #endif { int i; write_lock(&monitor_lock); Monitor_restore_calls(); monitor_started = 0; Monitor_queue_cleanup(); write_unlock(&monitor_lock); for(i = 5; i > 0; --i) { if(Monitor_ready_for_stop()) break; write_lock(&monitor_lock); Monitor_queue_cleanup(); write_unlock(&monitor_lock); pause("wait in stop" ,hz); } if(!Monitor_ready_for_stop()) PRN_ERR("KAVMOD: haven't waited to stop properly"); write_lock(&monitor_lock); TransportBufferFinit(&send_buff); TransportBufferFinit(&recv_buff); Monitor_kernel_finit(); Monitor_cleanup_calls(thr); write_unlock(&monitor_lock); return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int monitor_open (dev_t dev, int oflags, int devtype, struct proc * thr) { struct proc *p = thr; #else #if __FreeBSD_version >= 500003 int monitor_open (struct cdev * dev, int oflags, int devtype, struct thread *thr) #else int monitor_open (dev_t dev, int oflags, int devtype, struct thread *thr) #endif { struct proc *p = thr->td_proc; #endif file_info f_info; struct nameidata nd; struct vnode *tmpmnt = NULL; if (monitor_opened) return EACCES; #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, "/", curproc); #else NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, "/", curthread); #endif if (namei(&nd) != 0){ printf("kavmon error: failed to get root mount\n"); return EINVAL; } else { tmpmnt = nd.ni_rootdir; vref(tmpmnt); NDFREE(&nd, 0); } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 if (p->p_cred->p_ruid != 0) { #else if (p->p_ucred->cr_uid != 0) { #endif vrele(tmpmnt); return EACCES; } write_lock(&monitor_lock); Monitor_kernel_init(); if (get_exec_info(thr, &f_info)) { printf("Cannot determine file info\n"); write_unlock(&monitor_lock); vrele(tmpmnt); return EACCES; } Monitor_kernel_register_file(&f_info); TransportBufferInit(&send_buff); TransportBufferInit(&recv_buff); monitor_opened = 1; Monitor_ins_use(); write_unlock(&monitor_lock); orig_rootmnt = tmpmnt; return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int monitor_close (dev_t dev, int fflag, int devtype, struct proc * thr) #else #if __FreeBSD_version >= 500003 int monitor_close (struct cdev * dev, int fflag, int devtype, struct thread * thr) #else int monitor_close (dev_t dev, int fflag, int devtype, struct thread * thr) #endif #endif { if (monitor_started) { monitor_module_stop(thr); } if (orig_rootmnt != NULL) { vrele(orig_rootmnt); orig_rootmnt = NULL; } monitor_opened = 0; Monitor_dec_use(); return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version >= 500003 int monitor_read (struct cdev * adev, struct uio *uio, int ioflag) #else int monitor_read (dev_t dev, struct uio *uio, int ioflag) #endif { int len = 0; DEBUG_MSG("%s: count=%d",__FUNCTION__,uio->uio_resid); while (1) { write_lock(&send_buff_lock); if (send_buff.length) { break; } write_unlock(&send_buff_lock); if ( (ioflag & O_NONBLOCK) != 0 ) return EAGAIN; interruptible_sleep_on (&queue_empty_waitq); } len = MIN(uio->uio_resid, send_buff.length); if (uiomove ((char *)(send_buff.start), len, uio)) { write_unlock(&send_buff_lock); return EFAULT; } send_buff.start += len; send_buff.length -= len; write_unlock(&send_buff_lock); return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version >= 500003 int monitor_write (struct cdev * adev, struct uio *uio, int ioflag) { struct thread * thr = uio->uio_td; #else int monitor_write (dev_t dev, struct uio *uio, int ioflag) { struct proc * thr = uio->uio_procp; #endif int count = uio->uio_resid; DEBUG_MSG("%s: count=%d",__FUNCTION__,count); write_lock(&recv_buff_lock); fs_transport_buffer_check_size(&recv_buff, count); if (uiomove(recv_buff.start + recv_buff.length, count,uio)) { write_unlock(&recv_buff_lock); return EINVAL; } recv_buff.length += count; { TransportBufferEntry answer; while(TransportBufferGetNextPacket(&recv_buff, &answer)){ ProcessProtocolRequest((ProtocolData *)answer.begin,thr); } } write_unlock(&recv_buff_lock); return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int monitor_poll (dev_t dev, int events, struct proc *thr) #else #if defined (__FreeBSD_version) && __FreeBSD_version >= 500003 int monitor_poll (struct cdev * dev, int events, struct thread *thr) #else int monitor_poll (dev_t dev, int events, struct thread *thr) #endif #endif { unsigned int ret = (events & (POLLOUT | POLLWRNORM)); if (events & (POLLIN | POLLRDNORM)) { read_lock (&send_buff_lock); if (send_buff.length) ret |= POLLIN | POLLRDNORM; read_unlock (&send_buff_lock); } if (!ret) selrecord (thr, &queue_empty_select); return ret; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int monitor_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag,struct proc * thr) #else #if defined (__FreeBSD_version) && __FreeBSD_version >= 500003 int monitor_ioctl(struct cdev * dev, u_long cmd, caddr_t data, int flag,struct thread *thr) #else int monitor_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag,struct thread *thr) #endif #endif { char * path; file_info f_info; switch (cmd) { case FIONBIO: return (0); case FIOASYNC: return (0); case MONITOR_REGISTER_FILE_CMD: DEBUG_MSG("Register file command"); if (0 != get_file_from_userspace(thr, *(char **)data, &f_info, &path, NULL, NULL)) return EINVAL; MEM_FREE(path); Monitor_kernel_register_file(&f_info); return 0; case MONITOR_REGISTER_PROC_CMD: { monitor_register_proc_ioctl * params = (monitor_register_proc_ioctl *)data; DEBUG_MSG("Register proc command"); if (!params->pid) { DEBUG_MSG("pid is not set"); return EFAULT; } if (0 != get_file_from_userspace (thr,params->path, &f_info, &path, NULL, NULL)) { DEBUG_MSG("path is not set"); return EFAULT; } Monitor_kernel_register_proc((pid_t )params->pid,&f_info); DEBUG_MSG("Register proc command path=%s pid=%d",path, params->pid); MEM_FREE(path); } return 0; case MONITOR_CONFIG_CMD: { monitor_config_ioctl * params =(monitor_config_ioctl *) data ; int cache_size; if (!params) return EFAULT; cache_size = params->cache_size; m_config.cache_enable = cache_size?1:0; write_lock(&monitor_lock); Monitor_cache_start(cache_size); if(!monitor_started) { Monitor_intercept_calls(); monitor_started = 1; } write_unlock(&monitor_lock); } return 0; case MONITOR_CONFIG2_CMD: { monitor_config2_ioctl *params = (monitor_config2_ioctl *)data; int cache_size; if (!params) return EFAULT; if(params->version > FS_PROTOCOL_VERSION) return EOPNOTSUPP; cache_size = params->cache_size; m_config.cache_enable = cache_size?1:0; m_config.version = params->version; m_config.max_fname_len = params->max_fname_len; m_config.deny_too_long_fname = params->deny_too_long_fname; write_lock(&monitor_lock); Monitor_cache_start(cache_size); if(m_config.version < 3 && !monitor_started) { Monitor_intercept_calls(); monitor_started = 1; } write_unlock(&monitor_lock); } return 0; case MONITOR_START: if(m_config.version < 3) return EOPNOTSUPP; if(monitor_started) return EBUSY; write_lock(&monitor_lock); Monitor_intercept_calls(); monitor_started = 1; write_unlock(&monitor_lock); return 0; case MONITOR_CLEAR_CACHE_CMD: Monitor_cache_clear(); return 0; } return (ENOTTY); } void file_checked(void* ctx,const CheckFileResultInfoData * data) { DEBUG_MSG("%s: queue=%d",__FUNCTION__,data->queue_id); Monitor_queue_set_answer(data->queue_id, data->result); Monitor_queue_wakeup(data->queue_id); } void monitor_shutdown(void * ctx) { #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 struct proc * thr = (struct proc *) ctx; #else struct thread * thr = (struct thread *) ctx; #endif DEBUG_MSG("%s:",__FUNCTION__); monitor_module_stop(thr); }
💾 Save Changes
Cancel
📤 Upload File
×
Select File
Upload
Cancel
➕ Create New
×
Type
📄 File
📁 Folder
Name
Create
Cancel
✎ Rename Item
×
Current Name
New Name
Rename
Cancel
🔐 Change Permissions
×
Target File
Permission (e.g., 0755, 0644)
0755
0644
0777
Apply
Cancel