opt
/
kaspersky
/
kav4fs
/
src
/
kernel
/
module.freebsd
➕ New
📤 Upload
✎ Editing:
interceptor.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" #include <machine/md_var.h> #include <vm/vm.h> #include <vm/vm_param.h> #include <vm/pmap.h> #include <vm/vm_map.h> #include <sys/user.h> #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 static int file_really_written(struct file * file, struct proc * thr); static void remove_written_file(int fd,struct proc * thr); int check_after_close(struct proc *thr, struct file * file); #else static int file_really_written(struct file * fp, struct thread * thr); static void remove_written_file(int fd,struct thread * thr); int check_after_close(struct thread *thr, struct file * file); #endif #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 static int new_sys_open (struct proc *p, void *arg); static int new_sys_execve (struct proc *p, void *arg); static int new_sys_write(struct proc * p, void *arg); static int new_sys_close (struct proc *p, void *arg); static int new_sys_unlink(struct proc *p, void *arg); static int new_sys_rename(struct proc *p, void *arg); static void new_sys_exit(struct proc *td, void *arg); static int new_sys_setpgid(struct proc * td, void * arg); static int new_sys_dup2(struct proc *td, void * arg); static int new_sys_pwrite(struct proc *td, void * arg); static int write_handle(struct proc *thr,int fd); #else static int new_sys_open (struct thread *thr, void *arg); static int new_sys_execve (struct thread *thr, void *arg); static int new_sys_write (struct thread * thr, void *arg); static int new_sys_close (struct thread *thr, void *arg); static int new_sys_unlink(struct thread *thr, void *arg); static int new_sys_rename(struct thread *thr, void *arg); static void new_sys_exit(struct thread *td, void *arg); static int new_sys_setpgid(struct thread * td, void * arg); static int new_sys_dup2(struct thread *td, void * arg); static int new_sys_pwrite(struct thread *td, void * arg); static int write_handle(struct thread *thr,int fd); #endif typedef struct { struct file * file; #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 struct proc * tsk; #else struct thread * tsk; #endif struct list_head list; } file_t; static struct list_head written_files; static lock_declare(written_files_lock); #if defined (__FreeBSD_version) && __FreeBSD_version < 802000 extern char *syscallnames[]; #endif extern void * sys_call_table[]; static sy_call_t * old_sys_close; static sy_call_t * old_sys_write; static sy_call_t * old_sys_execve; static sy_call_t * old_sys_open; static sy_call_t * old_sys_unlink; static sy_call_t * old_sys_rename; static sy_call_t * old_sys_exit; static sy_call_t * old_sys_setpgid; static sy_call_t * old_sys_dup2; static sy_call_t * old_sys_pwrite; #define SYSCALL_INTERCEPT(sc_func)\ old_sys_##sc_func = sysent[SYS_##sc_func].sy_call;\ sysent[SYS_##sc_func].sy_call = new_sys_##sc_func; #define SYSCALL_INTERCEPT_EXIT\ old_sys_exit = sysent[SYS_exit].sy_call;\ sysent[SYS_exit].sy_call = (sy_call_t *)new_sys_exit; #define SYSCALL_RESTORE(sc_func)\ if(sysent[SYS_##sc_func].sy_call == new_sys_##sc_func)\ sysent[SYS_##sc_func].sy_call = old_sys_##sc_func; #define SYSCALL_RESTORE_EXIT\ if(sysent[SYS_exit].sy_call == (sy_call_t *)new_sys_exit)\ sysent[SYS_exit].sy_call = old_sys_exit; #if MODULE_ARCH==64 #include <compat/freebsd32/freebsd32_syscall.h> #include <compat/freebsd32/freebsd32_util.h> static sy_call_t * ia32_old_sys_close; static sy_call_t * ia32_old_sys_write; static sy_call_t * ia32_old_sys_execve; static sy_call_t * ia32_old_sys_open; static sy_call_t * ia32_old_sys_unlink; static sy_call_t * ia32_old_sys_rename; static sy_call_t * ia32_old_sys_exit; static sy_call_t * ia32_old_sys_setpgid; static sy_call_t * ia32_old_sys_dup2; static sy_call_t * ia32_old_sys_pwrite; extern struct sysentvec ia32_freebsd_sysvec; #define OLD_SYSCALL(sc_func, thr, arg) ({\ int res;\ if (curthread->td_proc->p_sysent == &ia32_freebsd_sysvec) {\ res = ia32_old_sys_##sc_func(thr, arg);\ } else {\ res = old_sys_##sc_func(thr, arg);\ }\ res; }) #define SYSCALL32_INTERCEPT(sc_func, sc_func32)\ ia32_old_sys_##sc_func = freebsd32_sysent[FREEBSD32_SYS_##sc_func32].sy_call;\ freebsd32_sysent[FREEBSD32_SYS_##sc_func32].sy_call = new_sys_##sc_func; #define SYSCALL32_INTERCEPT_EXIT\ ia32_old_sys_exit = freebsd32_sysent[FREEBSD32_SYS_exit].sy_call;\ freebsd32_sysent[FREEBSD32_SYS_exit].sy_call = (sy_call_t *)new_sys_exit; #define SYSCALL32_RESTORE(sc_func, sc_func32)\ if(freebsd32_sysent[FREEBSD32_SYS_##sc_func32].sy_call == new_sys_##sc_func)\ freebsd32_sysent[FREEBSD32_SYS_##sc_func32].sy_call = ia32_old_sys_##sc_func; #define SYSCALL32_RESTORE_EXIT\ if(freebsd32_sysent[FREEBSD32_SYS_exit].sy_call == (sy_call_t *)new_sys_exit)\ freebsd32_sysent[FREEBSD32_SYS_exit].sy_call = ia32_old_sys_exit; static void ia32_Monitor_intercept_calls (void) { SYSCALL32_INTERCEPT(execve, freebsd32_execve); SYSCALL32_INTERCEPT(open, open); SYSCALL32_INTERCEPT(write, write); SYSCALL32_INTERCEPT(close, close); SYSCALL32_INTERCEPT(unlink, unlink); SYSCALL32_INTERCEPT(rename, rename); SYSCALL32_INTERCEPT_EXIT; SYSCALL32_INTERCEPT(setpgid, setpgid); SYSCALL32_INTERCEPT(dup2, dup2); SYSCALL32_INTERCEPT(pwrite, freebsd32_pwrite); } static void ia32_Monitor_restore_calls(void) { SYSCALL32_RESTORE(execve, freebsd32_execve); SYSCALL32_RESTORE(open, open); SYSCALL32_RESTORE(write, write); SYSCALL32_RESTORE(close, close); SYSCALL32_RESTORE(unlink, unlink); SYSCALL32_RESTORE(rename, rename); SYSCALL32_RESTORE_EXIT; SYSCALL32_RESTORE(setpgid, setpgid); SYSCALL32_RESTORE(dup2, dup2); SYSCALL32_RESTORE(pwrite, freebsd32_pwrite); } #else /* 32bit architecture */ inline static void ia32_Monitor_intercept_calls (void) {} inline static void ia32_Monitor_restore_calls(void) {} #define OLD_SYSCALL(sc_func, thr, arg) old_sys_##sc_func(thr, arg); #endif static struct file * get_fp(struct filedesc * fdp, int fd) { struct file * fp = NULL; if ((unsigned)fd >= fdp->fd_nfiles || ((fp = fdp->fd_ofiles[fd])) == NULL || fp->f_type != DTYPE_VNODE || ((struct vnode *) fp->f_data)->v_type != VREG) { return NULL; } return fp; } /* void check_nonexist_proc(void) { struct list_head * f_list; file_t * file; struct proc * p; again: write_lock (&written_files_lock); list_for_each(f_list, &written_files) { struct task_struct * p; int found = 0; file = list_entry(f_list,file_t,list); sx_slock(&allproc_lock); FOREACH_PROC_IN_SYSTEM(p) { if (p->p_pid == file->tsk->pid) { found = 1; break;} } sx_sunlock(&allproc_lock); if (!found) { Monitor_kernel_unregister_proc(p->pid); list_del(&file->list); write_unlock (&written_files_lock); fput(file->file); MEM_FREE(file); goto again; } } write_unlock (&written_files_lock); } */ int Monitor_intercept_init(void) { KINIT_LIST_HEAD(&written_files); lock_init(&written_files_lock,"interceptor written files"); return 0; } int Monitor_intercept_deinit(void) { lock_finit(&written_files_lock); return 0; } int Monitor_intercept_calls (void) { SYSCALL_INTERCEPT(execve); SYSCALL_INTERCEPT(open); SYSCALL_INTERCEPT(write); SYSCALL_INTERCEPT(close); SYSCALL_INTERCEPT(unlink); SYSCALL_INTERCEPT(rename); SYSCALL_INTERCEPT_EXIT; SYSCALL_INTERCEPT(setpgid); SYSCALL_INTERCEPT(dup2); SYSCALL_INTERCEPT(pwrite); ia32_Monitor_intercept_calls(); return 0; } int Monitor_restore_calls(void) { SYSCALL_RESTORE(execve); SYSCALL_RESTORE(open); SYSCALL_RESTORE(write); SYSCALL_RESTORE(close); SYSCALL_RESTORE(unlink); SYSCALL_RESTORE(rename); SYSCALL_RESTORE_EXIT; SYSCALL_RESTORE(setpgid); SYSCALL_RESTORE(dup2); SYSCALL_RESTORE(pwrite); ia32_Monitor_restore_calls(); return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int Monitor_cleanup_calls (struct proc * thr) #else int Monitor_cleanup_calls (struct thread * thr) #endif { struct list_head * f_list; file_t * write_file; again: write_lock (&written_files_lock); list_for_each(f_list, &written_files) { write_file = list_entry(f_list,file_t,list); list_del(&write_file->list); write_unlock (&written_files_lock); fdrop(write_file->file, thr); MEM_FREE(write_file); goto again; } write_unlock (&written_files_lock); return 0; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int Process_trusted(struct proc * thr) { struct proc *p = thr; #else int Process_trusted(struct thread * thr) { struct proc *p = thr->td_proc; #endif file_info f_info; get_exec_info(thr, &f_info); return Monitor_kernel_trusted_proc( p->p_pid, &f_info); } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 void remove_written_file(int fd,struct proc * thr) { struct proc * p = thr; #else void remove_written_file(int fd,struct thread * thr) { struct proc * p = thr->td_proc; #endif register struct filedesc * fdp = p->p_fd; register struct file * fp; write_lock(&written_files_lock); COMPAT_FILEDESC_XLOCK(fdp); fp = get_fp(fdp,fd); if (!fp) goto l_exit; file_really_written(fp,thr); l_exit: COMPAT_FILEDESC_XUNLOCK(fdp); write_unlock(&written_files_lock); } /* * write_lock(&written_files_lock) must be acqired */ #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int file_really_written(struct file * file, struct proc * thr) #else int file_really_written(struct file * file, struct thread * thr) #endif { struct list_head * f_list; file_t * write_file; list_for_each(f_list, &written_files) { write_file = list_entry(f_list,file_t,list); if (write_file->file == file && write_file->tsk == thr) { list_del(&write_file->list); fdrop(write_file->file,thr); MEM_FREE(write_file); return 1; } } return 0; } static void send_notification_too_long(file_info *f_info, char *fname_part) { PackedBuffer request; if(1 == m_config.version) { MakeNotifyFileReq(&request, fname_part, FILE_NAME_TOO_LONG, f_info->dev, f_info->ino); } else { MakeNotifyFileReq2(&request, m_config.version, fname_part, FILE_NAME_TOO_LONG, f_info->dev, f_info->ino); } Monitor_module_send_data(&request); MEM_FREE(request.data); } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_open (struct proc * thr, void *arg) { struct proc *p = thr; #else int new_sys_open (struct thread * thr, void *arg) { struct proc *p = thr->td_proc; #endif char *k_filename, *fname_part = NULL; int res; struct open_args *uap = (struct open_args *)arg; file_info f_info; file_info_ex f_info_ex; Monitor_ins_use(); if(!arg || !thr || !monitor_started || Process_trusted(thr)) { res = OLD_SYSCALL(open, thr,arg); goto l_exit; } /* to get process registers int * fill_regs __P((struct proc *p, struct reg *regs)); */ res = get_file_from_userspace(thr, uap->path, &f_info, &k_filename, &f_info_ex, &fname_part); if(0 != res) { if(-1 == res) { res = OLD_SYSCALL(open, thr, arg); } else if(ENAMETOOLONG == res) { send_notification_too_long(&f_info, fname_part); if(fname_part) MEM_FREE(fname_part); if(!m_config.deny_too_long_fname) res = OLD_SYSCALL(open, thr, arg); } else if(ENOENT == res && uap->flags & O_CREAT) { res = OLD_SYSCALL(open, thr, arg); if(0 == res) { struct nameidata nd; NDINIT (&nd, LOOKUP, FOLLOW | MAKEENTRY, UIO_USERSPACE, uap->path, thr); namei(&nd); NDFREE (&nd, 0); } } goto l_exit; } res = OLD_SYSCALL(open, thr, arg); if(res) goto l_exit_free; if(0 == strncmp(k_filename, "/proc", 5)) goto l_exit_free; #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 res = Monitor_kernel_check_file(p->p_cred->p_ruid,p->p_cred->p_rgid,p->p_pid,k_filename, &f_info,FILE_OPEN_OPER, uap->flags,&res); #else res = Monitor_kernel_check_file(p->p_ucred->cr_uid,p->p_ucred->cr_gid, p->p_pid,k_filename, &f_info, &f_info_ex, FILE_OPEN_OPER, uap->flags,&res); #endif if(res) { struct close_args uap; #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 uap.fd = p->p_retval[0]; #else uap.fd = thr->td_retval[0]; #endif MEM_FREE (k_filename); OLD_SYSCALL(close, thr, &uap); goto l_exit; } l_exit_free: MEM_FREE(k_filename); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_execve (struct proc * thr, void *arg) { struct proc *p = thr; #else int new_sys_execve (struct thread *thr, void *arg) { struct proc *p = thr->td_proc; #endif struct execve_args * uap = (struct execve_args *) arg; int res; file_info f_info; file_info_ex f_info_ex; Monitor_ins_use(); if (!monitor_started || Process_trusted(thr)) { res = OLD_SYSCALL(execve, thr, arg); goto l_exit; } if ( p && arg ) { char * k_filename, *fname_part = NULL; res = get_file_from_userspace (thr, uap->fname, &f_info, &k_filename, &f_info_ex, &fname_part); if(0 == res) { if(0 != strncmp(k_filename, "/proc", 5)) { #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 res = Monitor_kernel_check_file(p->p_cred->p_ruid,p->p_cred->p_rgid,p->p_pid,k_filename, &f_info,FILE_OPEN_OPER,0,&res); #else res = Monitor_kernel_check_file(p->p_ucred->cr_uid,p->p_ucred->cr_gid,p->p_pid,k_filename, &f_info,&f_info_ex,FILE_OPEN_OPER,0,&res); #endif } MEM_FREE(k_filename); if (res) goto l_exit; } else if(ENAMETOOLONG == res) { send_notification_too_long(&f_info, fname_part); if(fname_part) MEM_FREE(fname_part); if(m_config.deny_too_long_fname) goto l_exit; } else goto l_exit; } res = OLD_SYSCALL(execve, thr, arg); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_write (struct proc * thr, void * arg) #else int new_sys_write (struct thread * thr, void * arg) #endif { struct write_args * uap = (struct write_args *) arg; int res,new_=0; Monitor_ins_use(); if(!monitor_started) { res = OLD_SYSCALL(write, thr, uap); goto l_exit; } new_ = write_handle(thr,uap->fd); res = OLD_SYSCALL(write, thr, uap); if (res && new_) remove_written_file(uap->fd,thr); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_close (struct proc * thr, void *arg) { struct proc *p = thr; #else int new_sys_close (struct thread *thr, void *arg) { struct proc *p = thr->td_proc; #endif register struct file * fp = NULL; register struct close_args * uap = (struct close_args *) arg; register struct filedesc * fdp = p->p_fd; int res; int file_written = 0; Monitor_ins_use(); if (!monitor_started || Process_trusted(thr)) { remove_written_file(uap->fd,thr); res = OLD_SYSCALL(close, thr, arg); goto l_exit; } write_lock(&written_files_lock); COMPAT_FILEDESC_XLOCK(fdp); fp = get_fp(fdp,uap->fd); if (fp) { file_written = file_really_written(fp,thr); fhold(fp); } FILEDESC_XUNLOCK(fdp); write_unlock(&written_files_lock); res = OLD_SYSCALL(close, thr, arg); if (file_written && monitor_started) { int av_err = check_after_close(thr,fp); if(av_err) res = av_err; } if (fp) fdrop(fp,thr); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_unlink(struct proc *thr, void *arg) #else int new_sys_unlink(struct thread *thr, void *arg) #endif { struct unlink_args * uap = (struct unlink_args *) arg; int res; char * k_filename; file_info f_info; Monitor_ins_use(); if (!monitor_started) { res = OLD_SYSCALL(unlink, thr, arg); goto l_exit; } res = get_file_from_userspace (thr, uap->path, &f_info, &k_filename, NULL, NULL); if(0 != res) { res = OLD_SYSCALL(unlink, thr, arg); goto l_exit; } if (Monitor_kernel_trusted_file(&f_info)) { res = EPERM; goto l_exit_free; } res = OLD_SYSCALL(unlink, thr, arg); if (!res && !Process_trusted(thr)) { PackedBuffer request; if(1 == m_config.version) { MakeNotifyFileReq(&request, k_filename, FILE_UNLINK_OPER, f_info.dev, f_info.ino); } else { MakeNotifyFileReq2(&request, m_config.version, k_filename, FILE_UNLINK_OPER, f_info.dev, f_info.ino); } Monitor_module_send_data(&request); MEM_FREE(request.data); Monitor_cache_del(f_info.dev,f_info.ino); } l_exit_free: MEM_FREE(k_filename); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_rename(struct proc *thr, void *arg) #else int new_sys_rename(struct thread *thr, void *arg) #endif { struct rename_args * uap = (struct rename_args *) arg; int res; char * k_old_filename; char * k_new_filename; file_info f_info_old, f_info_new; Monitor_ins_use(); if (!monitor_started) { res = OLD_SYSCALL(rename, thr, arg); goto l_exit; } get_file_from_userspace (thr, uap->from, &f_info_old, &k_old_filename, NULL, NULL); get_file_from_userspace (thr, uap->to, &f_info_new, &k_new_filename, NULL, NULL); if (k_old_filename && Monitor_kernel_trusted_file(&f_info_old)) { MEM_FREE(k_old_filename); if (k_new_filename) MEM_FREE (k_new_filename); res = EPERM; goto l_exit; } if (k_new_filename && Monitor_kernel_trusted_file(&f_info_new)) { MEM_FREE(k_new_filename); if (k_old_filename) MEM_FREE (k_old_filename); res = EPERM; goto l_exit; } res = OLD_SYSCALL(rename, thr, arg); if(!k_new_filename) get_file_from_userspace(thr, uap->to, &f_info_new, &k_new_filename, NULL, NULL); if (!res && !Process_trusted(thr)) { if (k_old_filename) { PackedBuffer request; if(1 == m_config.version) { MakeNotifyFileReq(&request, k_old_filename, FILE_UNLINK_OPER, f_info_old.dev, f_info_old.ino); } else { MakeNotifyFileReq2(&request, m_config.version, k_old_filename, FILE_UNLINK_OPER, f_info_old.dev, f_info_old.ino); } Monitor_module_send_data(&request); FinitPackedBuffer(&request); Monitor_cache_del(f_info_old.dev, f_info_old.ino); } if (k_new_filename) { PackedBuffer request; if(1 == m_config.version) { MakeNotifyFileReq(&request, k_new_filename, FILE_RENAME_OPER,f_info_new.dev, f_info_new.ino); } else { MakeNotifyFileReq2(&request, m_config.version, k_new_filename, FILE_RENAME_OPER,f_info_new.dev, f_info_new.ino); } Monitor_module_send_data(&request); FinitPackedBuffer(&request); Monitor_cache_del(f_info_new.dev,f_info_new.ino); } } if (k_old_filename) MEM_FREE (k_old_filename); if (k_new_filename) MEM_FREE (k_new_filename); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 void new_sys_exit(struct proc * thr, void * arg) { struct proc *p = thr; #else void new_sys_exit(struct thread * thr, void * arg) { struct proc *p = thr->td_proc; #endif struct sys_exit_args * uap = (struct sys_exit_args *) arg; struct list_head * f_list; file_t * check_file; int trusted; if (!monitor_started) { OLD_SYSCALL(exit, thr, uap); } trusted = Process_trusted(thr); again: write_lock (&written_files_lock); list_for_each(f_list, &written_files) { check_file = list_entry(f_list,file_t,list); if (check_file->tsk == thr) { list_del(&check_file->list); write_unlock (&written_files_lock); if (monitor_started && !trusted) { check_after_close(thr,check_file->file); } fdrop(check_file->file, thr); MEM_FREE(check_file); goto again; } } write_unlock (&written_files_lock); Monitor_kernel_unregister_proc(p->p_pid); // check_nonexist_proc(); OLD_SYSCALL(exit, thr, uap); } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_setpgid(struct proc * thr, void * arg) { struct proc *p = thr; #else int new_sys_setpgid(struct thread * thr, void * arg) { struct proc *p = thr->td_proc; #endif int res; register struct setpgid_args * uap = ( struct setpgid_args *) arg; Monitor_ins_use(); res = OLD_SYSCALL(setpgid, thr, arg); if (!monitor_started) goto l_exit; if (!res) { pid_t pid; register struct proc * tsk; pid = uap->pid?uap->pid:p->p_pid; tsk = pfind(pid); if (tsk) { pid = tsk->p_pid; PROC_UNLOCK(tsk); Monitor_kernel_unregister_proc(pid); } } l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_dup2(struct proc *thr, void * arg) { struct proc *p = thr; #else int new_sys_dup2(struct thread *thr, void * arg) { struct proc *p = thr->td_proc; #endif register struct dup2_args * uap = (struct dup2_args *) arg; int res; struct filedesc * fdp = NULL; struct file * fp = NULL; int file_written = 0; Monitor_ins_use(); if (!monitor_started) { res = OLD_SYSCALL(dup2, thr, arg); goto l_exit; } fdp = p->p_fd; write_lock(&written_files_lock); FILEDESC_XLOCK(fdp); fp = get_fp(fdp,uap->to); if (!fp) { FILEDESC_XUNLOCK(fdp); write_unlock(&written_files_lock); res = OLD_SYSCALL(dup2, thr, arg); goto l_exit; } file_written = file_really_written(fp,thr); fhold(fp); FILEDESC_XUNLOCK(fdp); write_unlock(&written_files_lock); res = OLD_SYSCALL(dup2, thr, arg); if (!res && file_written) check_after_close(thr,fp); fdrop(fp,thr); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int new_sys_pwrite(struct proc *thr, void * arg) #else int new_sys_pwrite(struct thread *thr, void * arg) #endif { struct pwrite_args * uap = (struct pwrite_args *) arg; int res, new_=0; Monitor_ins_use(); if (!monitor_started) { res = OLD_SYSCALL(pwrite, thr, uap); goto l_exit; } new_ = write_handle(thr,uap->fd); res = OLD_SYSCALL(pwrite, thr, uap); if((res < 0) && new_) remove_written_file(uap->fd,thr); l_exit: Monitor_dec_use(); return res; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int check_after_close(struct proc *thr, struct file * file) { struct proc *p = thr; #else int check_after_close(struct thread *thr, struct file * file) { struct proc *p = thr->td_proc; #endif char *k_filename; file_info f_info; int err = 0; file_info_ex f_info_ex; k_filename = get_filename_by_file(thr,file,&f_info, &f_info_ex); if (k_filename) { #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 err = Monitor_kernel_check_file(p->p_cred->p_ruid,p->p_cred->p_rgid, p->p_pid,k_filename, &f_info, FILE_CLOSE_OPER,file->f_flag,&err); #else err = Monitor_kernel_check_file(p->p_ucred->cr_uid,p->p_ucred->cr_gid, p->p_pid,k_filename, &f_info,&f_info_ex,FILE_CLOSE_OPER,file->f_flag,&err); #endif } if (k_filename) MEM_FREE (k_filename); return err; } #if defined (__FreeBSD_version) && __FreeBSD_version < 500000 int write_handle(struct proc *thr,int fd) { struct proc *p = thr; #else int write_handle(struct thread *thr,int fd) { struct proc *p = thr->td_proc; #endif int found; struct list_head * f_list; file_t * write_file; register struct filedesc * fdp = p->p_fd; register struct file * fp; write_lock (&written_files_lock); COMPAT_FILEDESC_XLOCK(fdp); fp = get_fp(fdp,fd); if (!fp) { goto done; } found = 0; list_for_each(f_list, &written_files) { write_file = list_entry(f_list,file_t,list); if (write_file->file == fp && write_file->tsk == thr) { found = 1; break; } } if (!found) { fhold(fp); COMPAT_FILEDESC_XUNLOCK(fdp); write_file = MEM_ALLOC(sizeof(file_t)); write_file->file = fp; write_file->tsk = thr; list_add(&write_file->list,&written_files); write_unlock (&written_files_lock); return 1; } done: COMPAT_FILEDESC_XUNLOCK(fdp); write_unlock (&written_files_lock); return 0; }
💾 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