getpeername总是给人不好的文件描述符 [英] getpeername always gives bad file descriptor

查看:201
本文介绍了getpeername总是给人不好的文件描述符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的code,那我试图用它来获得插座的另一端的地址,但 getpeername()总是失败, 坏文件描述符错误。我究竟做错了什么?

 的#include< ARPA / inet.h>
#包括LT&;&syscall.h GT;
#包括LT&;&errno.h中GT;
#包括LT&; netinet / in.h中>
#包括LT&;&string.h中GT;
#包括LT&; SYS / socket.h中>
#包括LT&;&stdio.h中GT;
#包括LT&; SYS / ptrace.h>
#包括LT&; SYS / types.h中>
#包括LT&; SYS / wait.h>
#包括LT&;&unistd.h中GT;
#包括LT&; SYS / user.h>
#包括LT&; SYS / syscall.h> / *对于SYS_WRITE等* /
#包括LT&;&stdlib.h中GT;#定义ORIG_RAX 15
#定义SYSCALL_MAXARGS 6
#定义RDI 14诠释的main()
{
    // **********声明和内存分配********** //
    ssiz​​e_t供大小;
    长sys_call_number,temp_long;
    INT状态,温度,I,J,K,标志;    结构SOCKADDR_IN ip_addr_struct;
    socklen_t的ip_addr_structlen = sizeof的(ip_addr_struct);
    结构user_regs_struct暂存器;    结构SOCKADDR_IN * connect_struct;    字符*文件路径=的malloc(1024);
    字符* fdpath =的malloc(1024);
    字符*消息=的malloc(1024);
    字符* connect_ip =的malloc(1024);
    字符*的ip_addr =的malloc(1024);    字符* temp_char1,* temp_char2;    将为pid_t PROC;    // **********越来越PID和连接处理********** //
    scanf函数(%d个,&安培; PROC);    ptrace函数(PTRACE_ATTACH,PROC,NULL,NULL);    // **********启动跟踪过程********** //    //在开关()的情况下用于确定特定系统的系统调用号调用//
    而(1)
    {
            等待(安培;状态);
            如果(WIFEXITED(状态))
            {
                的printf(****过程退出**** \\ n);
                打破;
            }
                ptrace函数(PTRACE_GETREGS,PROC,NULL,&安培;暂存器);
                sys_call_number = regs.orig_rax;        开关(sys_call_number)
        {
            案例44:
                的printf(SENDTO \\ n);
                // ***打印包含系统调用的参数寄存器值*** //
                的printf(%LLU - %LLU - %LLU - %LLU - %LLU - %LLU \\ n,regs.rdi,regs.rsi,regs.rdx,regs.r10,regs.r8,regs.r9);
                // ***获取对等地址*** //
                错误号= 0;
                TEMP = getpeername(regs.rdi,(结构sockaddr *)及ip_addr_struct,&安培; ip_addr_structlen);
                如果(临时== -1)
                {
                    的printf(错误是getpeername-%D-%S \\ n,温度,字符串错误(错误));
                    返回-1;
                }                INT端口= ntohs和(ip_addr_struct.sin_port);
                inet_ntop(AF_INET,及(ip_addr_struct.sin_addr)的ip_addr,1024);
                的printf(%D-%S \\ n,端口的ip_addr);
                端口= 0;
                // ***阅读邮件发送被// ***
                temp_char2 =消息;
                J = 0;
                而(J<(regs.rdx / 8))
                {
                    temp_long = ptrace函数(PTRACE_PEEKDATA,PROC,regs.rsi +(J * 8),NULL);
                    的memcpy(temp_char2,&安培; temp_long,8);
                    temp_char2 + = 8;
                    ++焦耳;
                }
                temp_long = ptrace函数(PTRACE_PEEKDATA,PROC,regs.rsi +(J * 8),NULL);
                的memcpy(temp_char2,&安培; temp_long,regs.rdx - (J * 8));
                消息[regs.rdx] ='\\ 0';
                的printf(MESSAGE-%S- \\ n \\ n,邮件);
            打破;
        }
    }
}

下面是一个这样的系统调用

输出

  SENDTO
14 - 32064144 - 884 - 16384 - 0 - 0
--1-错误的文件描述符
0-0.0.0.0
消息GET / gfe_rd = CR放大器; EI = 2WYzVLCjFq7M8gfLlICoDg HTTP / 1.1 ^ M
用户代理:NetSurf / 2.9(Linux的; x86_64的)^ M
主持人:www.google.co.in ^ M
接受:* /
接受编码:gzip ^ M
 饼干:preF = ID = yu3vtr7i452389b4o236v4t28o37v723tn8vt0783tnv0723p78 N823748923bt87t2387b473287b8273t48


解决方案

socket描述符是不是两个进程之间共享。所捕获的套接字描述符仅在跟踪过程有效,并且在示踪剂过程无效。这就是为什么 getpeername 抱怨糟糕的描述符。出租车从 ptrace的的手册:结果的ptrace的()系统调用提供了哪些父进程可以观察和控制的另一个进程的执行的手段,检查和改变其核心形象和寄存器。它主要用于实现断点调试和系统调用跟踪。结果没有话说他们共享进程空间,因此,它们不能共享套接字描述符,内存地址等。

I have the following code, that i am trying to use to get the address of the other end of the socket, but getpeername() always fails with bad file descriptor error. What am i doing wrong?

#include <arpa/inet.h>
#include<syscall.h>
#include<errno.h>
#include <netinet/in.h>
#include<string.h>
#include<sys/socket.h>
#include<stdio.h>
#include<sys/ptrace.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<sys/user.h>
#include<sys/syscall.h>   /* For SYS_write etc */
#include<stdlib.h>

#define ORIG_RAX 15
#define SYSCALL_MAXARGS 6
#define RDI 14

int main()
{
    //**********declarations and memory allocations**********//
    ssize_t size;
    long sys_call_number, temp_long;
    int status, temp, i, j, k, flag;

    struct sockaddr_in ip_addr_struct;
    socklen_t ip_addr_structlen = sizeof(ip_addr_struct);
    struct user_regs_struct regs;

    struct sockaddr_in* connect_struct;

    char* filepath = malloc(1024);
    char* fdpath = malloc(1024);
    char* message = malloc(1024);
    char* connect_ip = malloc(1024); 
    char* ip_addr = malloc(1024);

    char* temp_char1,* temp_char2;

    pid_t proc;

    //**********getting pid and attaching to process**********//
    scanf("%d",&proc);

    ptrace(PTRACE_ATTACH,proc, NULL, NULL);

    //**********starting the trace process**********//

    //The system call number used in switch() case to determine particular system   calls// 
    while(1)
    {
            wait(&status);
            if(WIFEXITED(status))
            {
                printf("****Process exited****\n");
                break;
            }
                ptrace(PTRACE_GETREGS, proc, NULL, &regs);
                sys_call_number = regs.orig_rax;

        switch(sys_call_number)
        {
            case 44:
                printf("sendto\n");
                //***printing the register values containing system call parameters***//
                printf("%llu - %llu - %llu - %llu - %llu - %llu\n", regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9);
                //***getting the peer address***//
                errno = 0;
                temp = getpeername(regs.rdi, (struct sockaddr *)&ip_addr_struct, &ip_addr_structlen);
                if(temp == -1)
                {
                    printf("error is getpeername-%d-%s\n",temp,strerror(errno));
                    return -1;
                }

                int port = ntohs(ip_addr_struct.sin_port);
                inet_ntop(AF_INET, &(ip_addr_struct.sin_addr), ip_addr, 1024);
                printf("%d-%s\n", port, ip_addr);
                port = 0;
                //***reading message being send***//
                temp_char2 = message;
                j = 0;
                while( j < (regs.rdx/8) )
                {
                    temp_long = ptrace(PTRACE_PEEKDATA, proc, regs.rsi + (j*8) , NULL);
                    memcpy(temp_char2, &temp_long, 8);
                    temp_char2 += 8;
                    ++j;
                }
                temp_long = ptrace(PTRACE_PEEKDATA, proc, regs.rsi + (j*8) , NULL);
                memcpy(temp_char2, &temp_long, regs.rdx - (j*8) );
                message[regs.rdx] = '\0';
                printf("Message-%s-\n\n", message);
            break;
        }
    }
}

Here is the output from one such system call

sendto
14 - 32064144 - 884 - 16384 - 0 - 0
--1-Bad file descriptor
0-0.0.0.0
Message-GET /?gfe_rd=cr&ei=2WYzVLCjFq7M8gfLlICoDg HTTP/1.1^M
User-Agent: NetSurf/2.9 (Linux; x86_64)^M
Host: www.google.co.in^M
Accept: */
Accept-Encoding: gzip^M
 Cookie:PREF=ID=yu3vtr7i452389b4o236v4t28o37v723tn8vt0783tnv0723p78 N823748923bt87t2387b473287b8273t48

解决方案

socket descriptor is not shared between two processes. the captured socket descriptor is only effective in the traced process, and not effective in the tracer process. that's why getpeername complains bad descriptor.
from the manual of ptrace:
The ptrace() system call provides a means by which a parent process may observe and control the execution of another process, and examine and change its core image and registers. It is primarily used to implement breakpoint debugging and system call tracing.
there's no word says they share process space, thus, they can not share socket descriptors, memory address, etc..

这篇关于getpeername总是给人不好的文件描述符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆