pidfd_getfd Menduplikasi Descriptor Target ke Proses Pemanggil
pidfd_getfd() dapat menempatkan duplikat file descriptor milik proses lain ke tabel descriptor proses pemanggil. Descriptor hasil menjadi milik pemanggil, tetapi tetap merujuk ke open file description yang sama dengan descriptor terpilih pada proses target.
Batas ini penting karena operasi tersebut tidak membuka ulang pathname, membangun ulang socket, atau membuat posisi file independen. Kernel menduplikasi referensi yang sudah ada melintasi batas proses.
pidfd dan targetfd menunjuk dua hal berbeda
Pemanggilan menerima PID file descriptor serta nomor descriptor milik proses target:
int fd = syscall(SYS_pidfd_getfd, pidfd, targetfd, 0);pidfd mengidentifikasi task target dan dapat diperoleh melalui pidfd_open() untuk proses yang sudah berjalan. targetfd ditafsirkan di dalam tabel file descriptor target, bukan tabel milik pemanggil.
Jika berhasil, kernel mengalokasikan nomor descriptor baru pada pemanggil. Nilai numeriknya tidak harus sama atau berkaitan dengan targetfd.
Argumen flags masih dicadangkan dan saat ini harus bernilai nol. Nilai selain nol menghasilkan EINVAL.
Kedua descriptor berbagi satu open file description
Properti semantik utamanya adalah state open-file yang dibagi. Descriptor target dan descriptor hasil merujuk ke open file description yang sama.
Pada regular file, operasi yang memajukan file offset melalui satu descriptor memengaruhi offset yang terlihat melalui descriptor lainnya. File status flags yang melekat pada open file description juga dibagi.
Perilaku ini berbeda dari dua proses yang masing-masing memanggil open() pada pathname yang sama. Pemanggilan open() terpisah umumnya menghasilkan open file description terpisah, sehingga offset dan status open-file dapat berubah secara independen.
Aturan objek bersama juga berlaku pada tipe descriptor lain. Jika descriptor target merujuk ke socket, hasil duplikasi merujuk ke objek socket yang sama, bukan socket baru dengan parameter serupa.
Descriptor flags berada pada lapisan berbeda. Linux memasang FD_CLOEXEC pada descriptor yang dikembalikan pidfd_getfd(), sehingga execve() pada pemanggil tidak mempertahankannya kecuali flag tersebut dihapus secara eksplisit.
Proses target tidak perlu mengirim descriptor
UNIX domain socket dapat memindahkan referensi descriptor memakai SCM_RIGHTS, tetapi mekanisme itu memerlukan komunikasi antarpihak. Proses pengirim harus ikut membentuk dan mengirim control message.
pidfd_getfd() memakai model koordinasi berbeda. Proses target tidak perlu menjalankan protokol transfer descriptor. Dengan PID file descriptor yang sesuai, nomor descriptor target yang valid, dan izin yang cukup, pemanggil dapat meminta duplikat langsung kepada kernel.
Karakteristik ini berguna bagi process supervisor, sistem inspeksi, dan rancangan lain yang mengendalikan akses descriptor dari luar proses target. Namun, mekanisme tersebut tidak membuat akses descriptor menjadi bebas izin.
Ptrace access check menjadi batas izin
Duplikasi descriptor lintas proses dilindungi oleh pemeriksaan PTRACE_MODE_ATTACH_REALCREDS. Kegagalan pemeriksaan tersebut menghasilkan EPERM.
Mekanisme akses ptrace mempertimbangkan credential proses, capability, kondisi target seperti dumpability, serta kebijakan Linux Security Module. Karena itu, user ID yang sama tidak berarti operasi selalu diizinkan pada setiap deployment. Kebijakan seperti pembatasan Yama dapat memperketat akses kelas attach.
Model izin ini juga berarti pidfd bukan token otorisasi. Kepemilikan pidfd memberi identitas proses yang stabil tanpa hanya bergantung pada PID numerik yang dapat dipakai ulang, tetapi pidfd_getfd() tetap menjalankan pemeriksaan aksesnya sendiri.
Validitas descriptor diperiksa saat pemanggilan
targetfd harus menunjuk descriptor yang masih terbuka pada proses yang dirujuk oleh pidfd. Jika tidak, pemanggilan gagal dengan EBADF. PID file descriptor yang tidak valid juga menghasilkan EBADF.
Jika proses target telah berakhir dan sudah di-wait, pemanggilan dapat gagal dengan ESRCH. pidfd menghindari ambiguitas identitas proses, tetapi tidak mempertahankan tabel descriptor proses yang telah selesai untuk waktu tak terbatas.
Pemanggil juga memerlukan ruang pada tabel descriptornya sendiri. Kehabisan kapasitas descriptor per proses atau secara sistem dapat menghasilkan EMFILE atau ENFILE.
Rangkaian kegagalan ini memisahkan tiga batas: identitas proses yang stabil melalui pidfd, keberadaan descriptor pada target, dan ketersediaan resource pada pemanggil.
Duplikat membentuk batas operasi bersama
Setelah pemanggilan berhasil, kedua proses memiliki entry descriptor yang menuju open file description yang sama. Menutup salah satu descriptor hanya melepaskan referensi milik proses tersebut; descriptor lain tetap valid selama masih ada referensi ke objek yang sama.
Operasi yang mengubah state open-file bersama dapat terlihat melintasi batas proses. Seek oleh satu proses dapat mengubah posisi yang digunakan proses lain jika objek memiliki file offset. Perubahan file status flags bersama juga dapat terlihat melalui kedua referensi.
Itulah batas utama pidfd_getfd(): hasilnya bukan snapshot descriptor eksternal, melainkan referensi aktif lain menuju state open-file kernel yang sama dan diperoleh melalui process handle dengan pemeriksaan izin.