Nomor file descriptor hanya memiliki arti di dalam tabel descriptor suatu proses, tetapi objek kernel di balik nomor tersebut dapat dipakai bersama oleh beberapa proses. Linux pidfd_getfd() menjembatani dua ruang itu: syscall ini menerima PID file descriptor beserta nomor descriptor dari proses yang dirujuk, lalu memasang descriptor duplikat pada proses pemanggil. Descriptor baru tersebut merujuk ke open file description yang sama dengan descriptor target.
Properti terakhir itu merupakan batas utama. pidfd_getfd() tidak membuka ulang pathname, menyalin byte, atau membuat posisi file yang independen. Operasi ini menduplikasi referensi kernel yang sudah ada sehingga semantik state bersama dapat memengaruhi kedua proses.
Nomor descriptor tetap bersifat lokal terhadap proses
Misalkan proses A memiliki descriptor 7 dan proses B juga memiliki descriptor 7. Kesamaan integer tersebut tidak menyatakan hubungan apa pun. Setiap proses mempunyai tabel descriptor yang memetakan integer kecil ke open file description yang dikelola kernel.
PID file descriptor mengidentifikasi task tanpa hanya bergantung pada PID numerik yang kelak dapat digunakan kembali. Dengan sebuah pidfd, bentuk operasinya adalah:
int localfd = syscall(SYS_pidfd_getfd, pidfd, targetfd, 0);Jika berhasil, localfd adalah nomor descriptor baru yang dialokasikan di proses pemanggil. targetfd tetap merupakan nomor yang ditafsirkan dalam proses yang dirujuk oleh pidfd. Kedua integer dapat berbeda dan tidak ada syarat agar nilainya sama.
Kontrak flags saat ini mensyaratkan nilai nol. Nilai nonnol gagal dengan EINVAL, sehingga argumen tersebut tetap dicadangkan untuk perluasan di masa depan.
Duplikat memakai open file description yang sama
Linux memisahkan entri file descriptor dari open file description yang dirujuknya. Open file description menyimpan state seperti offset file saat ini dan file status flags. Karena pidfd_getfd() mengarahkan descriptor baru ke open file description yang sama, perubahan terhadap state bersama dapat terlihat melalui kedua descriptor.
Untuk file biasa yang dapat di-seek, operasi yang memajukan offset melalui satu descriptor mengubah posisi yang kemudian terlihat melalui descriptor lainnya. File status flags yang terkait dengan open file description juga dipakai bersama. Ini merupakan kelas sharing yang dihasilkan oleh duplikasi descriptor, bukan isolasi state yang dihasilkan oleh open() baru.
Descriptor flags berada pada lapisan berbeda. Descriptor yang dikembalikan oleh pidfd_getfd() memiliki FD_CLOEXEC. Pengaturan itu melekat pada entri descriptor yang baru dipasang, bukan pada open file description bersama, sehingga tidak menerapkan perilaku close-on-exec pada descriptor milik proses target.
Objek bersama juga tidak harus berupa file biasa. Jika descriptor merujuk ke socket, operasi yang tersedia pada objek socket tersebut dapat dilakukan melalui duplikat sesuai aturan API normal. Syscall ini dengan demikian memberikan akses yang dapat digunakan terhadap objek kernel yang sudah ada, bukan sekadar metadata yang mendeskripsikannya.
Akses dibatasi pemeriksaan izin mode ptrace
Sebuah proses tidak dapat memakai pidfd_getfd() sebagai ekstraktor descriptor tanpa batas. Linux menerapkan pemeriksaan access mode PTRACE_MODE_ATTACH_REALCREDS terhadap proses yang dirujuk oleh pidfd. Kegagalan pemeriksaan tersebut menghasilkan EPERM.
Pemeriksaan akses ptrace mempertimbangkan credential proses, capability, status dumpable target, dan kebijakan Linux Security Module. Hasil tepatnya karena itu dapat bergantung pada konfigurasi keamanan seperti LSM yang aktif, selain relasi UID. Memiliki pidfd saja tidak berarti proses memiliki izin untuk menduplikasi descriptor arbitrer dari proses yang dirujuk.
Pemisahan ini penting pada batas privilege. Pidfd menyediakan referensi proses yang stabil, sedangkan pemeriksaan akses terpisah mengatur operasi lintas proses yang sensitif ini. Menganggap kepemilikan pidfd sebagai capability umum untuk seluruh operasi terkait pidfd akan memberikan cakupan otoritas yang terlalu luas.
Lifetime descriptor target membentuk batas race
targetfd harus masih menunjuk descriptor terbuka di proses target saat syscall dieksekusi. Jika descriptor itu tidak terbuka, operasi gagal dengan EBADF. Proses target yang secara konkuren menutup dan menggunakan kembali nomor descriptor dapat mengubah objek yang ditunjuk oleh targetfd numerik sebelum operasi duplikasi dijalankan kernel.
Pidfd mengatasi penggunaan ulang identitas proses, bukan penggunaan ulang nomor descriptor di dalam proses tersebut. Protokol yang memperoleh nomor descriptor dari observasi eksternal tetap memerlukan aturan sinkronisasi atau ownership bila nomor itu harus terus menunjuk objek tertentu sampai duplikasi terjadi.
Setelah pidfd_getfd() berhasil, penutupan descriptor asli oleh target tidak membatalkan duplikat milik pemanggil. Pemanggilan yang berhasil telah memasang referensi lain ke open file description yang sama. Lifetime berikutnya mengikuti aturan referensi descriptor dan objek dasar seperti biasa.
Batas resource tetap berlaku pada proses pemanggil
Pemasangan duplikat memakai satu slot descriptor pada proses pemanggil. Jika proses pemanggil telah mencapai batas descriptor terbuka per proses, syscall dapat gagal dengan EMFILE. Kehabisan resource open-file tingkat sistem dapat menghasilkan ENFILE.
Kegagalan tersebut tetap dapat terjadi ketika descriptor target valid dan pemeriksaan akses mengizinkan duplikasi. Akuisisi lintas proses tidak melewati accounting descriptor pada proses penerima.
Jika pidfd bukan PID file descriptor yang valid, EBADF juga dapat terjadi. Jika proses yang dirujuk sudah tidak ada setelah terminasi dan proses tersebut telah di-reap, kegagalan yang terdokumentasi adalah ESRCH. Kondisi ini memisahkan referensi proses yang tidak valid dari nomor descriptor yang tidak valid serta kegagalan izin.
SCM_RIGHTS dan pidfd_getfd memiliki model transfer berbeda
UNIX domain socket dapat mentransfer descriptor dengan SCM_RIGHTS. Mekanisme itu memerlukan koneksi socket dan kerja sama dari proses yang mengirim descriptor. Penerima memperoleh akses karena pengirim berpartisipasi secara eksplisit dalam protokol transfer.
pidfd_getfd() menghapus kebutuhan kerja sama tersebut. Pemanggil menamai proses target melalui pidfd dan descriptor melalui nomor dalam tabel target, lalu kernel menerapkan pemeriksaan izin mode ptrace. Sifat ini cocok untuk supervisor proses dan infrastruktur inspeksi yang otoritasnya berasal dari relasi proses atau capability, bukan dari kanal pengiriman descriptor pada level aplikasi.
Perbedaan tersebut tidak membuat kedua mekanisme dapat saling menggantikan begitu saja. SCM_RIGHTS menempatkan transfer descriptor di dalam protokol pesan eksplisit dan dapat membawa descriptor yang dipilih pengirim. pidfd_getfd() bergantung pada pengetahuan eksternal mengenai nomor descriptor target serta otoritas inspeksi lintas proses.
Identitas proses yang stabil tidak mengisolasi state file
pidfd_getfd() menggabungkan referensi proses yang stabil dengan duplikasi descriptor lintas proses, tetapi hasilnya tetap berupa referensi bersama. Pemanggil memperoleh entri tabel descriptor sendiri dan flag FD_CLOEXEC sendiri, sedangkan offset file, file status flags, dan objek kernel dasar berada pada open file description atau objek yang dipakai bersama.
Batas ini memiliki dampak operasional. Supervisor yang memperoleh descriptor dapat memengaruhi state yang terlihat oleh proses target, dan proses target dapat memengaruhi state bersama yang terlihat oleh supervisor. Syscall ini memberikan akses terkontrol ke objek yang sudah ada; hasilnya bukan snapshot atau handle independen dengan state yang terpisah.