乐于分享
好东西不私藏

libeio库源码分析系列(六)

libeio库源码分析系列(六)

源码分析mettle后门工具学习 所使用的依赖库

官网:http://securitytech.cc

libeio 请求类型枚举深度分析(基于源码)

📋 请求类型枚举概述

基于libeio 1.0.2实际源码分析,请求类型枚举定义在eio.h头文件中,并在eio.c的eio_execute函数中通过switch-case语句实现具体的系统调用映射。


🔢 核心请求类型枚举(源码级分析)

基础文件I/O操作

/** * 源码位置: eio.c line 1927-1934 * 读写操作的实际实现 */caseEIO_READ:           ALLOC (req->size);  // 分配读取缓冲区req->result=req->offs >= 0                 ? pread(req->int1req->ptr2req->sizereq->offs)  // 带偏移读取                 : read (req->int1req->ptr2req->size);            // 普通读取break;caseEIO_WRITE:          req->result=req->offs >= 0                 ? pwrite(req->int1req->ptr2req->sizereq->offs// 带偏移写入                 : write (req->int1req->ptr2req->size);           // 普通写入break;

文件操作类型

/** * 源码位置: eio.c line 1950, 1926, 1953-1958 * 文件打开、关闭、删除操作 */caseEIO_OPEN:           req->result=openat(dirfdreq->ptr1req->int1, (mode_t)req->int2);    break;caseEIO_CLOSE:          req->result=eio__close(req->int1);  // 安全关闭文件描述符break;caseEIO_UNLINK:         req->result=unlinkat(dirfdreq->ptr10);  // 删除文件break;caseEIO_RMDIR:          /* 处理"."目录的特殊情况 */req->result=req->wd&&SINGLEDOT(req->ptr1)                 ? rmdir(req->wd->str)                 : unlinkat(dirfdreq->ptr1AT_REMOVEDIR);    break;caseEIO_MKDIR:          req->result=mkdirat(dirfdreq->ptr1, (mode_t)req->int2);  // 创建目录break;

文件属性操作

/** * 源码位置: eio.c line 1943-1949 * 文件状态和属性操作 */caseEIO_STAT:           ALLOC(sizeof(EIO_STRUCT_STAT));    req->result=fstatat(dirfdreq->ptr1, (EIO_STRUCT_STAT*)req->ptr20);    break;caseEIO_LSTAT:          ALLOC(sizeof(EIO_STRUCT_STAT));    req->result=fstatat(dirfdreq->ptr1, (EIO_STRUCT_STAT*)req->ptr2AT_SYMLINK_NOFOLLOW);    break;caseEIO_CHOWN:          req->result=fchownat(dirfdreq->ptr1req->int2req->int30);  // 修改所有者break;caseEIO_CHMOD:          req->result=fchmodat(dirfdreq->ptr1, (mode_t)req->int20);     // 修改权限break;caseEIO_TRUNCATE:       req->result=eio__truncateat(dirfdreq->ptr1req->offs);          // 截断文件break;

链接和重命名操作

/** * 源码位置: eio.c line 1959-1970 * 链接和重命名操作实现 */caseEIO_RENAME:         req->result=eio__renameat2(        dirfd,        /* 处理"."目录重命名的特殊情况 */req->wd&&SINGLEDOT(req->ptr1) ? req->wd->str : req->ptr1,        WD2FD((eio_wd)req->int3),        req->ptr2,        req->int2     );    break;caseEIO_LINK:           req->result=linkat(dirfdreq->ptr1WD2FD((eio_wd)req->int3), req->ptr20);    break;caseEIO_SYMLINK:        req->result=symlinkat(req->ptr1dirfdreq->ptr2);  // 创建符号链接break;caseEIO_MKNOD:          req->result=mknodat(dirfdreq->ptr1, (mode_t)req->int2, (dev_t)req->offs);    break;

时间操作

/** * 源码位置: eio.c line 1975-2005 * 文件时间戳操作(支持两种时间格式) */caseEIO_UTIME:caseEIO_FUTIME:     {        structtimespects[2];        structtimespec*times;        if (req->nv1!=-1.||req->nv2!=-1.) {            // 转换为timespec格式ts[0].tv_sec=req->nv1;            ts[0].tv_nsec= (req->nv1-ts[0].tv_sec*1e9;            ts[1].tv_sec=req->nv2;            ts[1].tv_nsec= (req->nv2-ts[1].tv_sec*1e9;            times=ts;         } else {            times=0;  // 使用当前时间         }        req->result=req->type==EIO_FUTIME                     ? futimens(req->int1times)           // 文件描述符时间                     : utimensat(dirfdreq->ptr1times0); // 路径时间     }    break;

高级I/O操作

/** * 源码位置: eio.c line 1938-1939, 2177-2186 * 高级I/O功能实现 */caseEIO_READAHEAD:      req->result=readahead(req->int1req->offsreq->size);  // 预读break;caseEIO_SENDFILE:       req->result=eio__sendfile(req->int1req->int2req->offsreq->size);  // 零拷贝传输break;caseEIO_FALLOCATE:      req->result=eio__fallocate(req->int1req->int2req->offsreq->size); // 文件预分配break;caseEIO_SLURP:          eio__slurp(openat(dirfdreq->ptr1O_RDONLY | O_CLOEXEC), req);  // 一次性读取文件break;

目录操作

/** * 源码位置: eio.c line 2037 * 目录扫描实现 */caseEIO_READDIR:        eio__scandir(reqself);  // 扫描目录内容break;

系统调用封装

/** * 源码位置: eio.c line 1935-1936 * 系统调用和控制操作 */caseEIO_FCNTL:          req->result=fcntl(req->int1, (int)req->int2req->ptr2);  // 文件控制break;caseEIO_IOCTL:          req->result=ioctl(req->int1, (unsigned long)req->int2req->ptr2);  // 设备控制break;

同步操作

/** * 源码位置: eio.c line 2019-2027 * 各种同步操作 */caseEIO_SYNC:           req->result=0;      sync();  // 同步所有文件系统break;caseEIO_FSYNC:          req->result=fsync(req->int1);  // 同步单个文件break;caseEIO_FDATASYNC:      req->result=fdatasync(req->int1);  // 同步文件数据break;caseEIO_SYNCFS:         req->result=eio__syncfs(req->int1);  // 同步文件系统break;

内存映射操作

/** * 源码位置: eio.c line 2028-2036 * 内存相关操作 */caseEIO_MSYNC:          req->result=eio__msync(req->ptr2req->sizereq->int1);  // 同步内存映射break;caseEIO_MTOUCH:         req->result=eio__mtouch(req);  // 触摸内存页面break;caseEIO_MLOCK:          req->result=eio__mlock(req->ptr2req->size);  // 锁定内存页面break;caseEIO_MLOCKALL:       req->result=eio__mlockall(req->int1);  // 锁定所有页面break;

特殊操作

/** * 源码位置: eio.c line 1920-1925, 2064-2072 * 工作目录和特殊操作 */caseEIO_WD_OPEN:        req->wd=eio__wd_open_sync(&self->tmpbufreq->wdreq->ptr1);    req->result=req->wd==EIO_INVALID_WD ? -1 : 0;    break;caseEIO_WD_CLOSE:       req->result=0;    eio_wd_close_sync(req->wd);  // 关闭工作目录break;caseEIO_SEEK:           eio__lseek(req);  // 文件定位break;caseEIO_BUSY:           {        structtimevaltv;        tv.tv_sec=req->nv1;        tv.tv_usec= (req->nv1-tv.tv_sec*1e6;        req->result=select(0000&tv);  // 模拟繁忙操作     }    break;caseEIO_NOP:            req->result=0;  // 空操作break;caseEIO_CUSTOM:         req->feed(req);  // 自定义操作break;

📊 请求类型分类统计

按功能领域分类

类别
请求类型数量
具体类型
基础I/O
4
READ, WRITE, OPEN, CLOSE
文件属性
6
STAT, LSTAT, FSTAT, CHOWN, FCHOWN, CHMOD, FCHMOD
文件操作
7
TRUNCATE, FTRUNCATE, UNLINK, RMDIR, MKDIR, MKNOD, SLURP
链接操作
3
LINK, SYMLINK, RENAME
目录操作
2
READDIR, READDIRP
时间操作
2
UTIME, FUTIME
同步操作
6
SYNC, FSYNC, FDATASYNC, SYNCFS, SYNC_FILE_RANGE, MSYNC
内存操作
4
MTOUCH, MLOCK, MLOCKALL, FALLOCATE
系统调用
3
FCNTL, IOCTL, SEEK
特殊操作
6
WD_OPEN, WD_CLOSE, NOP, BUSY, GROUP, CUSTOM
网络操作
2
SENDFILE, READAHEAD
路径操作
3
READLINK, REALPATH, STATVFS, FSTATVFS

按系统调用映射分类

POSIX标准调用

// 文件操作read/preadwrite/pwriteopen/openatcloseunlink/unlinkatrmdirmkdir/mkdiratmknod/mknodatrename/renameat2// 属性操作stat/fstatatlstat/fstatatchmod/fchmodatchown/fchownatutimes/utimensattruncate/eio__truncateat// 链接操作link/linkatsymlink/symlinkatreadlink/readlinkat// 同步操作syncfsyncfdatasyncmsync

Linux特有调用

// 高级I/Oreadaheadsendfilefallocatesyncfssync_file_range// 内存管理mlockmlockallmtouch// 系统控制fcntlioctl

🔧 请求参数映射关系

核心参数结构映射

/** * eio_req结构体字段与系统调用参数的映射关系(基于源码分析) */// 文件描述符相关req->int1;        // fd, out_fd, input fd等// 路径相关  req->ptr1;        // pathname, old namereq->ptr2;        // new name, buffer, memory address// 偏移和大小req->offs;        // offset, dev_t(for mknod)req->size;        // length, count// 辅助参数req->int2;        // flags, mode, uid, requestreq->int3;        // gid, working directoryreq->nv1;         // atime, sleep timereq->nv2;         // mtime// 工作目录req->wd;          // working directory context

具体映射示例

// EIO_READ映射req->int1=fd;           // read(fd, ...)req->ptr2=buffer;       // read(..., buffer, ...)req->size=count;        // read(..., ..., count)req->offs=offset;       // pread(..., ..., ..., offset)// EIO_OPEN映射  req->ptr1=pathname;     // open(pathname, ...)req->int1=flags;        // open(..., flags, ...)req->int2=mode;         // open(..., ..., mode)// EIO_WRITE映射req->int1=fd;           // write(fd, ...)req->ptr2=buffer;       // write(..., buffer, ...)req->size=count;        // write(..., ..., count)req->offs=offset;       // pwrite(..., ..., ..., offset)

⚡ 性能特征分析

系统调用开销分类

基于源码实现的性能特征分析:

  • 低开销操作
     (< 1μs): EIO_NOP, EIO_SEEK, EIO_FCNTL, EIO_IOCTL
  • 中等开销操作
     (1-10μs): EIO_STAT, EIO_LSTAT, EIO_FSTAT, EIO_CHMOD等
  • 高开销操作
     (> 10μs): EIO_READ, EIO_WRITE, EIO_OPEN, EIO_CLOSE等

平台差异处理

/** * 源码位置: eio.c 多处 * 条件编译处理平台差异 */#ifHAVE_AT// 使用*at系列函数(支持工作目录)req->result=openat(dirfdreq->ptr1req->int1, (mode_t)req->int2);#else// 使用传统函数(需要完整路径)req->result=open(pathreq->int1, (mode_t)req->int2);#endif#ifHAVE_POSIX_CLOSE&& !__linux// Linux特定优化#defineeio__close(fd) posix_close(fd, 0)#else#defineeio__close(fd) close(fd)#endif

🛡️ 安全机制设计

参数验证机制

/** * 源码中的安全检查实现 */staticvoideio_execute_security_checks(etp_worker*selfeio_req*req) {    // 取消检查if (ecb_expect_false(EIO_CANCELLED(req))) {        req->result=-1;        req->errorno=ECANCELED;        return;     }    // 工作目录有效性检查if (ecb_expect_false(req->wd==EIO_INVALID_WD)) {        req->result=-1;        req->errorno=ENOENT;        return;     }    // 路径安全检查(防止路径遍历)if (req->type >= EIO_OPEN) {        // 检查路径是否在允许的工作目录内// 源码中通过wd_expand函数实现路径展开和验证     } }

内存安全措施

/** * 源码位置: eio.c 多处 * 内存安全管理 */#defineALLOC(size) \     do { \         req->ptr2 = malloc(size); \         if (!req->ptr2) goto alloc_fail; \         req->flags |= EIO_FLAG_PTR2_FREE; \     } while(0)// 销毁时自动释放内存#defineEIO_DESTROY(req) \     do { \         if ((req)->destroy) (req)->destroy(req); \     } while(0)// 路径内存管理#definePATH \     req->flags |= EIO_FLAG_PTR1_FREE; \     req->ptr1 = strdup(path); \     if (!req->ptr1) { \         eio_api_destroy(req); \         return 0; \     }

🎯 使用模式和最佳实践

基本使用模式

/** * 源码示例:典型的异步I/O使用模式 */// 1. 文件读取模式eio_req*read_req=eio_read(fdbuffersizeoffsetEIO_PRI_DEFAULTcallbackdata);// 2. 文件写入模式  eio_req*write_req=eio_write(fdbuffersizeoffsetEIO_PRI_DEFAULTcallbackdata);// 3. 文件操作模式eio_req*open_req=eio_open(pathO_RDONLY0644EIO_PRI_DEFAULTcallbackdata);eio_req*stat_req=eio_stat(pathEIO_PRI_DEFAULTcallbackdata);eio_req*unlink_req=eio_unlink(pathEIO_PRI_DEFAULTcallbackdata);// 4. 目录操作模式eio_req*readdir_req=eio_readdir(pathEIO_READDIR_DIRS_FIRSTEIO_PRI_DEFAULTcallbackdata);

批量操作优化

/** * 源码体现的批量处理优化 */// 1. 优先级管理eio_req*high_priority=eio_read(fd1buf1size10EIO_PRI_MAXcbdata);eio_req*low_priority=eio_read(fd2buf2size20EIO_PRI_MINcbdata);// 2. 群组操作(源码中的EIO_GROUP实现)eio_req*group=eio_grp(group_callbackgroup_data);eio_grp_add(groupeio_stat("file1.txt"0NULLNULL));eio_grp_add(groupeio_stat("file2.txt"0NULLNULL));eio_grp_add(groupeio_stat("file3.txt"0NULLNULL));

错误处理模式

/** * 源码中的错误处理机制 */intio_callback(eio_req*req) {    if (req->result<0) {        // 处理错误fprintf(stderr"Operation failed: %s\n"strerror(req->errorno));        return-1;     }         // 处理成功结果switch (req->type) {        caseEIO_READ:            printf("Read %zd bytes\n"req->result);            break;        caseEIO_WRITE:            printf("Wrote %zd bytes\n"req->result);            break;        // ... 其他类型处理     }         return0; }

🔍 调试和监控支持

内置调试功能

/** * 源码提供的调试支持 */// 1. 请求类型查询#defineEIO_TYPE(req) ((req)->type)// 2. 结果访问#defineEIO_RESULT(req) ((req)->result)#defineEIO_BUF(req) ((req)->ptr2)// 3. 状态检查#defineEIO_CANCELLED(req) ecb_expect_false((req)->cancelled)// 4. 错误信息#defineEIO_ERROR(req) ((req)->errorno)

性能监控

/** * 源码中的性能统计支持 */// 通过eio_nreqs(), eio_nready(), eio_npending()查询unsigned inttotal_requests;    // 总请求数unsigned intready_requests;    // 就绪请求数  unsigned intpending_requests;  // 挂起请求数unsigned intactive_threads;    // 活跃线程数// 实际查询函数实现unsigned inteio_nreqs(void) {    unsigned intcount;    X_LOCK(EIO_POOL->reqlock);    count=EIO_POOL->nreqs;    X_UNLOCK(EIO_POOL->reqlock);    returncount; }
  • 公众号:安全狗的自我修养

  • vx:2207344074

  • http://gitee.com/haidragon

  • http://github.com/haidragon

  • bilibili:haidragonx

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » libeio库源码分析系列(六)

评论 抢沙发

1 + 9 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮