diff options
Diffstat (limited to 'src/hook_lib/file_hook.c')
-rw-r--r-- | src/hook_lib/file_hook.c | 149 |
1 files changed, 131 insertions, 18 deletions
diff --git a/src/hook_lib/file_hook.c b/src/hook_lib/file_hook.c index 36e1328..7318149 100644 --- a/src/hook_lib/file_hook.c +++ b/src/hook_lib/file_hook.c @@ -56,11 +56,14 @@ int (*_readdir64_r)(DIR *dirp, struct dirent64 *entry, int (*_access)(const char *pathname, int mode); int (*_euidaccess)(const char *pathname, int mode); +int (*_faccessat)(int dirfd, const char *pathname, int mode, int flags); // these stat functions are only source level standart of glibc // we no catch fxstat int (*___xstat)(int vers, const char *name, struct stat *buf); +int (*___xstat64)(int vers, const char *name, struct stat64 *buf); int (*___lxstat)(int vers, const char *name, struct stat *buf); +int (*___lxstat64)(int vers, const char *name, struct stat64 *buf); int (*_execve)(const char *filename, char *const argv[],char *const envp[]); int (*_execv)(const char *path, char *const argv[]); @@ -165,10 +168,14 @@ void _init() { _access=(int (*)(const char *pathname, int mode)) dlsym(RTLD_NEXT, "access"); _euidaccess=(int (*)(const char *pathname, int mode)) dlsym(RTLD_NEXT, "euidaccess"); - + _faccessat=(int(*)(int dirfd, const char *pathname, int mode, int flags)) dlsym(RTLD_NEXT, "faccessat"); + + ___xstat=(int (*)(int vers, const char *name, struct stat *buf)) dlsym(RTLD_NEXT, "__xstat"); - ___lxstat=(int (*)(int vers, const char *name, struct stat *buf)) dlsym(RTLD_NEXT, "__lxstat"); - + ___xstat64=(int (*)(int vers, const char *name, struct stat64 *buf)) dlsym(RTLD_NEXT, "__xstat64"); + ___lxstat=(int (*)(int vers, const char *name, struct stat *buf)) dlsym(RTLD_NEXT, "__lxstat"); + ___lxstat64=(int (*)(int vers, const char *name, struct stat64 *buf)) dlsym(RTLD_NEXT, "__lxstat64"); + _fork = (pid_t (*)()) dlsym(RTLD_NEXT, "fork"); _execve = (int (*)(const char *filename, char *const argv[],char *const envp[])) dlsym(RTLD_NEXT, "execve"); @@ -190,7 +197,7 @@ void _init() { _read==NULL || _write==NULL || _mmap==NULL || _readdir==NULL || _readdir64 == NULL || _readdir_r==NULL || _readdir64_r==NULL || - _access==NULL || _euidaccess==NULL || + _access==NULL || _euidaccess==NULL || _faccessat==NULL || _fork==NULL || _execve==NULL || _execv==NULL || _execvp==NULL || _execvpe==NULL || _fexecve==NULL || _system==NULL || _setenv==NULL || _close==NULL) { @@ -271,6 +278,48 @@ ssize_t __get_path_by_fd(int fd, char *output, int output_len) { } /* + * Realpath. Resolved path is empty string on error. If path not exists, + * returns the path as is, but resolving current dir . Arguments must be not null +*/ +char *myrealpath(const char *path, char *resolved){ + char *ret=realpath(path,resolved); + if(ret!=NULL) + return ret; + + if(path==NULL) + goto error; + + // difficult case: error returned + char *dest; + + if(path[0]!='/') { + if(! getcwd(resolved,MAXPATHLEN-2)) + goto error; + + dest= resolved+strlen(resolved); + dest[0]='/'; + dest++; + dest[0]='\0'; + } else { + dest = resolved; + } + + char *border=resolved+MAXPATHLEN-1; // not crossing it and not stepping on it + if(dest>=border) + goto error; + + strncpy(dest, path, border-dest); + + return resolved; + +error: + resolved[0]=0; + return NULL; + +} + + +/* * Ask for event "alloweness" */ static int __is_event_allowed(const char *event_type,const char *filename, char* stage) { @@ -337,7 +386,7 @@ void __fixenvp(char *const envp[], char *envp_new[]) { int open(const char * path, int flags, mode_t mode) { int ret; char fullpath[MAXPATHLEN]; - realpath(path,fullpath); + myrealpath(path,fullpath); char *stage=__get_stage(); if(! __is_event_allowed("open",fullpath,stage)) { __log_event("open",fullpath,"DENIED",errno,stage); @@ -360,7 +409,7 @@ int open(const char * path, int flags, mode_t mode) { int open64(const char * path, int flags, mode_t mode) { int ret; char fullpath[MAXPATHLEN]; - realpath(path,fullpath); + myrealpath(path,fullpath); char *stage=__get_stage(); if(! __is_event_allowed("open",fullpath,stage)) { __log_event("open",path,"DENIED",errno,stage); @@ -383,7 +432,7 @@ int open64(const char * path, int flags, mode_t mode) { FILE *fopen(const char *path, const char *mode) { FILE *ret; char fullpath[MAXPATHLEN]; - realpath(path,fullpath); + myrealpath(path,fullpath); char *stage=__get_stage(); if(! __is_event_allowed("open",fullpath,stage)) { @@ -405,7 +454,7 @@ FILE *fopen(const char *path, const char *mode) { FILE *fopen64(const char *path, const char *mode) { FILE *ret; char fullpath[MAXPATHLEN]; - realpath(path,fullpath); + myrealpath(path,fullpath); char *stage=__get_stage(); if(! __is_event_allowed("open",fullpath,stage)) { @@ -779,7 +828,7 @@ struct dirent *readdir(DIR *dirp) { snprintf(fullpath,MAXPATHLEN,"%s/%s",dirpath,ep->d_name); char abspath[MAXPATHLEN]; - realpath(fullpath,abspath); + myrealpath(fullpath,abspath); if(! __is_event_allowed("open",abspath,stage)) { //__log_event("open",abspath,"DENIED",errno,stage); @@ -809,7 +858,7 @@ struct dirent64 *readdir64(DIR *dirp) { snprintf(fullpath,MAXPATHLEN,"%s/%s",dirpath,ep->d_name); char abspath[MAXPATHLEN]; - realpath(fullpath,abspath); + myrealpath(fullpath,abspath); if(! __is_event_allowed("open",abspath,stage)) { //__log_event("open",abspath,"DENIED",errno,stage); @@ -845,7 +894,7 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result){ snprintf(fullpath,MAXPATHLEN,"%s/%s",dirpath,entry->d_name); char abspath[MAXPATHLEN]; - realpath(fullpath,abspath); + myrealpath(fullpath,abspath); if(! __is_event_allowed("open",abspath,stage)) { //__log_event("open",abspath,"DENIED",errno,stage); @@ -881,7 +930,7 @@ int readdir64_r(DIR *dirp, struct dirent64 *entry, struct dirent64 **result){ snprintf(fullpath,MAXPATHLEN,"%s/%s",dirpath,entry->d_name); char abspath[MAXPATHLEN]; - realpath(fullpath,abspath); + myrealpath(fullpath,abspath); if(! __is_event_allowed("open",abspath,stage)) { //__log_event("open",abspath,"DENIED",errno,stage); @@ -899,10 +948,13 @@ int __xstat (int vers, const char *name, struct stat *buf) { char *stage=__get_stage(); char fullpath[MAXPATHLEN]; - realpath(name,fullpath); + myrealpath(name,fullpath); - if(! __is_event_allowed("open",fullpath,stage)) + if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); + errno=2; return -1; + } if(___xstat==NULL) return -1; @@ -910,14 +962,33 @@ int __xstat (int vers, const char *name, struct stat *buf) { return ___xstat(vers,name,buf); } -int __lxstat (int vers, const char *name, struct stat *buf) { +int __xstat64 (int vers, const char *name, struct stat64 *buf) { char *stage=__get_stage(); char fullpath[MAXPATHLEN]; - realpath(name,fullpath); + myrealpath(name,fullpath); + + if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); + errno=2; + return -1; + } + + if(___xstat64==NULL) + return -1; + + return ___xstat64(vers,name,buf); +} + +int __lxstat (int vers, const char *name, struct stat *buf) { + char *stage=__get_stage(); + + char fullpath[MAXPATHLEN]; + myrealpath(name,fullpath); if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); errno = 2; return -1; } @@ -928,13 +999,33 @@ int __lxstat (int vers, const char *name, struct stat *buf) { return ___lxstat(vers,name,buf); } +int __lxstat64 (int vers, const char *name, struct stat64 *buf) { + char *stage=__get_stage(); + + char fullpath[MAXPATHLEN]; + myrealpath(name,fullpath); + + if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); + errno = 2; + return -1; + } + + if(___lxstat64==NULL) + return -1; + + return ___lxstat64(vers,name,buf); +} + + int access(const char *pathname, int mode) { char *stage=__get_stage(); char fullpath[MAXPATHLEN]; - realpath(pathname,fullpath); + myrealpath(pathname,fullpath); if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); errno = 2; return -1; } @@ -946,9 +1037,10 @@ int euidaccess(const char *pathname, int mode) { char *stage=__get_stage(); char fullpath[MAXPATHLEN]; - realpath(pathname,fullpath); + myrealpath(pathname,fullpath); if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); errno = 2; return -1; } @@ -956,6 +1048,27 @@ int euidaccess(const char *pathname, int mode) { return _euidaccess(pathname,mode); } +int faccessat(int dirfd, const char *pathname, int mode, int flags){ + char *stage=__get_stage(); + + + char filepath[MAXPATHLEN]; + char fullpath[MAXPATHLEN]; + int len=__get_path_by_fd(dirfd,filepath,MAXPATHLEN); + if(len==-1) + filepath[0]=0; + strcat(filepath,"/"); + strcat(filepath,pathname); + myrealpath(filepath,fullpath); + + if(! __is_event_allowed("open",fullpath,stage)) { + __log_event("open",fullpath,"DENIED",errno,stage); + errno = 2; + return -1; + } + + return _faccessat(dirfd,pathname,mode,flags); +} int setenv(const char *name, const char *value, int overwrite) { |