diff options
author | 2011-08-21 14:26:52 +0000 | |
---|---|---|
committer | 2011-08-21 14:26:52 +0000 | |
commit | fdbe127317c8f8df356d6f772c613557243fcc63 (patch) | |
tree | 46033c358c9cb4d5362ef051a2fdd97af298a5ea | |
parent | documentation fixes (diff) | |
download | autodep-fdbe127317c8f8df356d6f772c613557243fcc63.tar.gz autodep-fdbe127317c8f8df356d6f772c613557243fcc63.tar.bz2 autodep-fdbe127317c8f8df356d6f772c613557243fcc63.zip |
big code commit in the last day before pencils down date
-rwxr-xr-x | src/autodep/autodep | 87 | ||||
-rw-r--r-- | src/autodep/helpers/events_analysis.py | 1 | ||||
-rw-r--r-- | src/autodep/logfs/fstracer.py | 10 | ||||
-rw-r--r-- | src/autodep/package_utils/portage_misc_functions.py | 41 | ||||
-rw-r--r-- | src/hook_lib/file_hook.c | 149 |
5 files changed, 236 insertions, 52 deletions
diff --git a/src/autodep/autodep b/src/autodep/autodep index f202d0d..034c47a 100755 --- a/src/autodep/autodep +++ b/src/autodep/autodep @@ -80,10 +80,35 @@ def init_runtime_vars(portage_api, options,args): else: runtime_vars["is_emerge"]=False + runtime_vars["deps_all"]=[] + + # find a full path to the program + program_path=None + program_name=args[0] + def is_exe(fpath): + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + fpath, fname = os.path.split(program_name) + if fpath: + if is_exe(program_name): + program_path=program_name + else: + for path in os.environ["PATH"].split(os.pathsep): + exe_file = os.path.join(path, program_name) + if is_exe(exe_file): + program_path=exe_file + + if program_path==None: + print("Failed to find the program %s. Check its existance." + % program_name) + exit(1) + + runtime_vars["full_path"]=program_path + return runtime_vars -def get_filter_function(options,system_packages,portage_api): +def get_filter_function(options,args,system_packages,portage_api): # handling --block # exits if package name is bad if not options.packages and not options.strict_block: @@ -107,14 +132,18 @@ def get_filter_function(options,system_packages,portage_api): #exit(1) elif options.strict_block: # this option is very strict # because blocking logic is complex + print "Building a list of files to block. This may take some time" # we get list of all files and substract list of allowed files from it allfiles=portage_utils.get_all_packages_files() allowedpkgs=[] allowedpkgs+=system_packages if runtime_vars["is_emerge"]: # blocking logic for emerge + print "Notice: you can use emerge_strict command instead of autodep emerge." + print "Using this command allows to build any number of a packages.\n" + # including all dependencies of portage - allowedpkgs+=list(portage_api.get_deps('portage')) + allowedpkgs+=list(portage_api.get_dep("portage",["RDEPEND"])) (emergeaction ,emergeopts, emergefiles)=runtime_vars["emerge_parameters"] if len(emergefiles)>1: print "You can't install several packages with option -b" @@ -122,35 +151,40 @@ def get_filter_function(options,system_packages,portage_api): if len(runtime_vars["mergelist"])!=1: print "You can't install several packages with option -b." print "Emerge tried to install several packages: %s. " % runtime_vars["mergelist"] - print "You can force emerge to merge a package wit hout any other "\ + print "You can force emerge to merge a package without any other "\ "packages with emerge --nodeps option or you can install these "\ "packages first" exit(1) pkg=runtime_vars["mergelist"][0] - depslist=list(portage_api.get_deps(pkg)) + depslist=list(portage_api.get_deps_for_package_building(pkg)) allowedpkgs+=depslist + # manually add all python interpreters to this list + allowedpkgs+=["python"] else: - pass # TODO: blocking logic for non-emerge proccesses - - # always include current python interpreter - #print allowedpkgs - #allowedpkgs+=portage_utils.getpackagesbyfiles(sys.executable) - #print allowedpkgs + program_path=runtime_vars["full_path"] + file_to_package=portage_utils.getpackagesbyfiles([program_path]) + if program_path not in file_to_package: + print "Failed to find a package for %s" % program_path + else: + allowedpkgs+=[file_to_package[program_path]] + depslist=list( + portage_api.get_deps(file_to_package[program_path],["RDEPEND"])) + allowedpkgs+=depslist + + print allowedpkgs + + # remember the allowedpkgs in deps_all. It is bad to do it here. + runtime_vars["deps_all"]=allowedpkgs allowedfiles=[] for pkg in allowedpkgs: allowedfiles+=portage_utils.getfilesbypackage(pkg) - # manually add all python interpreters to this list - allowedfiles+=portage_utils.getfilesbypackage('python') - # manually add sandbox to this list - #allowedfiles+=portage_utils.getfilesbypackage('sandbox') - + allowedfiles=set(allowedfiles) deniedfiles=allfiles-allowedfiles - print "The list size is about %dM" % (int(sys.getsizeof(deniedfiles))/1024/1024) def filter(eventname,filename,stage): if filename in deniedfiles: @@ -158,15 +192,13 @@ def get_filter_function(options,system_packages,portage_api): return True return filter - - portage_api, system_packages=init_environment() options,args=parse_args() runtime_vars=init_runtime_vars(portage_api,options,args) color_printer=colorize_output.color_printer(not options.nocolor) -filter_function=get_filter_function(options,system_packages,portage_api) +filter_function=get_filter_function(options,args,system_packages,portage_api) # launching program events=logfs.fstracer.getfsevents(args[0], args,approach=options.approach,filterproc=filter_function) @@ -180,11 +212,11 @@ if runtime_vars["is_emerge"]: runtime_vars["deps_buildtime"]=set([]) for pkg in runtime_vars["mergelist"]: runtime_vars["deps_all"]=runtime_vars["deps_all"].union( - portage_api.get_deps(pkg,["DEPEND", "RDEPEND"])) + portage_api.get_deps_for_package_building(pkg)) runtime_vars["deps_buildtime"]=runtime_vars["deps_buildtime"].union( portage_api.get_dep(pkg,["DEPEND"])) - runtime_vars["deps_portage"]=portage_api.get_deps('portage',["DEPEND", "RDEPEND"]) + runtime_vars["deps_portage"]=portage_api.get_dep('portage',["RDEPEND"]) #pkgs=portage_log_parser.get_list_of_merged_packages( @@ -274,10 +306,9 @@ for package in sorted(packagesinfo): if package=="unknown" and not options.verbose: continue - if package in system_packages and not options.verbose: - continue - is_pkg_in_dep=runtime_vars["is_emerge"] and package in runtime_vars["deps_all"] + is_pkg_in_dep=package in runtime_vars["deps_all"] + is_pkg_in_system=package in system_packages is_pkg_in_portage_dep=runtime_vars["is_emerge"] and package in runtime_vars["deps_portage"] is_pkg_python="dev-lang/python" in package @@ -310,8 +341,10 @@ for package in sorted(packagesinfo): ] - if not runtime_vars["is_emerge"] or is_pkg_in_dep: + if is_pkg_in_dep: color_printer.printmsg("text","[OK]") + elif is_pkg_in_system: + color_printer.printmsg("text","[SYSTEM]") elif is_pkg_in_portage_dep: color_printer.printmsg("text","[PORTAGE DEP]") elif is_pkg_python: @@ -345,8 +378,8 @@ for package in sorted(packagesinfo): filescounter+=1 if options.show_files: continue - elif filescounter>=options.numfiles: - print " ..." + elif filescounter>options.numfiles: + print " ... and %d more ...\n" % (len(filenames)-10) break # print not founded files with stages diff --git a/src/autodep/helpers/events_analysis.py b/src/autodep/helpers/events_analysis.py index eba903a..b1e467d 100644 --- a/src/autodep/helpers/events_analysis.py +++ b/src/autodep/helpers/events_analysis.py @@ -39,4 +39,3 @@ def is_package_useful(pkg,stages,files): return True -
\ No newline at end of file diff --git a/src/autodep/logfs/fstracer.py b/src/autodep/logfs/fstracer.py index 58507bb..f33d1fb 100644 --- a/src/autodep/logfs/fstracer.py +++ b/src/autodep/logfs/fstracer.py @@ -175,11 +175,11 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter) if message[4]=="ASKING": if filterproc(message[1],message[2],message[3]): #print "Allowing an access to %s" % message[2] - s.sendall("ALLOW\0"); # TODO: think about flush here + s.sendall("ALLOW\0"); else: - print "Blocking an access to %s" % message[2] - s.sendall("DENY\0"); # TODO: think about flush here + #print "Blocking an access to %s" % message[2] + s.sendall("DENY\0"); else: eventname,filename,stage,result=message[1:5] @@ -189,6 +189,10 @@ def getfsevents(prog_name,arguments,approach="hooklib",filterproc=defaultfilter) hashofsucesses=events[stage][0] hashoffailures=events[stage][1] + + if result=="DENIED": + print "Blocking an access to %s" % filename + if result=="OK": if not filename in hashofsucesses: diff --git a/src/autodep/package_utils/portage_misc_functions.py b/src/autodep/package_utils/portage_misc_functions.py index 95c4ce4..aa95845 100644 --- a/src/autodep/package_utils/portage_misc_functions.py +++ b/src/autodep/package_utils/portage_misc_functions.py @@ -117,13 +117,25 @@ class portage_api: return ret # we found the best visible match in common tree + #import pdb; pdb.set_trace() metadata = dict(zip(self.metadata_keys, self.portdb.aux_get(pkg, self.metadata_keys))) dep_str = " ".join(metadata[k] for k in dep_type) + + # the IUSE default are very important for us + iuse_defaults=[ + u[1:] for u in metadata.get("IUSE",'').split() if u.startswith("+")] + + use=self.use.split() + + for u in iuse_defaults: + if u not in use: + use.append(u) + success, atoms = portage.dep_check(dep_str, None, self.settings, - myuse=self.use.split(), trees=portage.db, myroot=self.settings["ROOT"]) + myuse=use, trees=portage.db, myroot=self.settings["ROOT"]) if not success: return ret @@ -176,8 +188,18 @@ class portage_api: metadata = dict(zip(self.metadata_keys, self.vardb.aux_get(p, self.metadata_keys))) dep_str = " ".join(metadata[k] for k in dep_type) - - success, atoms = portage.dep_check(dep_str, None, self.settings, myuse=self.use.split(), + + # the IUSE default are very important for us + iuse_defaults=[ + u[1:] for u in metadata.get("IUSE",'').split() if u.startswith("+")] + + use=self.use.split() + + for u in iuse_defaults: + if u not in use: + use.append(u) + + success, atoms = portage.dep_check(dep_str, None, self.settings, myuse=use, trees=portage.db, myroot=self.settings["ROOT"]) if not success: @@ -195,6 +217,19 @@ class portage_api: unknown_packages.add(pkg) return ret + def get_deps_for_package_building(self, pkg): + """ + returns buildtime dependencies of current package and + all runtime dependencies of that buildtime dependencies + """ + buildtime_deps=self.get_dep(pkg, ["DEPEND"]) + runtime_deps=set() + for dep in buildtime_deps: + runtime_deps=runtime_deps.union(self.get_deps(dep,["RDEPEND"])) + + ret=buildtime_deps.union(runtime_deps) + return ret + def get_system_packages_list(self): """ returns all packages from system set. They are always implicit dependencies 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) { |