Linux 및 OpenBSD에서 getsockopt SO_PEERCRED의 다른 순서

Linux 및 OpenBSD에서 getsockopt SO_PEERCRED의 다른 순서

Python에서 Unix 소켓 피어 자격 증명을 얻으려고 합니다.

나는 이 코드를 사용하고 있습니다 :

peercred = conn.getsockopt(socket.SOL_SOCKET, socket.SO_PEERCRED, struct.calcsize("3i"))
pid, uid, gid = struct.unpack("3i", peercred)

이는 Linux에서는 잘 작동하지만 OpenBSD에서는 순서가 다릅니다. OpenBsd에서는 순서가 [uid, gid, pid]반대입니다.

이 차이의 원인은 무엇입니까? 언제 어떤 주문을 사용해야 하는지 어떻게 알 수 있나요?

내가 시도한 Linux 시스템은 x86_64 아키텍처에서 실행되고 openbsd 시스템은 amd64 아키텍처에서 실행됩니다.

답변1

저는 Python 프로그래머는 아니지만 여러분이 sys.platform.

SO_PEERCRED표준화된 인터페이스가 아닌 실제 구조/바이너리 인터페이스는 시스템마다 다릅니다.

Linux에서 정의는 다음과 같습니다 /usr/include/bits/socket.h.

struct ucred {
        __u32   pid;
        __u32   uid;
        __u32   gid;
};

OpenBSD에서 정의는 다음과 같습니다 /usr/include/sys/socket.h.

struct sockpeercred {
        uid_t           uid;            /* effective user id */
        gid_t           gid;            /* effective group id */
        pid_t           pid;
};

( , uid_tOpenBSD에서는 32비트 gid_t이기도 함 )pid_t

다른 시스템(예: Solaris, FreeBSD)은 완전히 다른 인터페이스를 갖습니다. - "시스템 독립적인" 방식으로 피어 자격 증명을 얻는 일부 코드의 경우 볼 수 있습니다.update_client_creds()Heimdal 소스 코드의 함수( 직접 또는 getpeereid(3)대신 OpenBSD 및 FreeBSD의 라이브러리 함수 사용 )SO_PEERCREDLOCAL_PEERCRED

그럼에도 불구하고 이 방법으로 얻은 자격 증명은 소켓을 호출한 프로세스(더 이상 존재하지 않을 수 있는 프로세스)의 자격 증명이 되며 connect(2)자격 listen(2)증명에 쓰거나 읽음으로써 소켓을 실제로 사용한 프로세스의 자격 증명일 필요는 없습니다.

답변2

cffi"API 수준" 접근 방식을 사용할 수 있습니다 . 이를 위해서는 C 컴파일러가 필요하지만 호환 가능한 시스템에서 컴파일한 다음 결과를 재사용할 수 있습니다.

https://cffi.readthedocs.io/en/latest/overview.html#api-mode-calling-the-c-standard-library

struct passwd이는 정확한 C 레이아웃 ("ABI 수준"이 아니라 "API 수준"임) 과는 아무런 관련이 없습니다 .

관련 정보