SCM_RIGHTS memungkinkan satu proses mengirim referensi ke file yang sudah terbuka melalui Unix domain socket. Penerima memperoleh file descriptor di tabel descriptornya sendiri, tetapi transfer tersebut tidak membuka ulang pathname atau menyalin objek kernel. Pada Linux, referensi yang dihasilkan memiliki semantik setara dengan menduplikasi descriptor milik pengirim ke proses penerima.

Perbedaan ini penting ketika batas proses juga menjadi batas otoritas. Supervisor dapat membuka socket, file, pipe, device, atau objek lain berbasis descriptor lalu memberikan referensi yang sudah terbentuk kepada worker. Worker menerima akses ke objek yang telah terbuka, termasuk state open-file yang dapat tetap dipakai bersama dengan pengirim.

Nilai yang ditransfer bukan nomor descriptor

File descriptor adalah integer lokal proses yang mengindeks sebuah entri pada tabel descriptor proses tersebut. Mengirim integer 7 sebagai payload biasa tidak memiliki efek khusus; descriptor 7 pada proses lain dapat menunjuk objek yang sama sekali berbeda atau tidak menunjuk objek apa pun.

SCM_RIGHTS merupakan ancillary data yang melekat pada pesan Unix domain socket. Kernel menafsirkan nomor descriptor yang diberikan dalam konteks proses pengirim, mengambil referensi ke objek terbuka yang terkait, lalu memasang descriptor untuk referensi tersebut pada penerima. Nilai numerik yang dipilih untuk penerima bersifat lokal bagi penerima itu.

Bentuk ringkas sisi pengirim dalam C adalah:

char control[CMSG_SPACE(sizeof(int))] = {0};
struct msghdr msg = {0};
struct cmsghdr *cmsg;

msg.msg_control = control;
msg.msg_controllen = sizeof(control);

cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));

Transfer sebenarnya berlangsung melalui sendmsg(). Penerima memakai recvmsg() dan memeriksa record ancillary, bukan memperlakukan control buffer sebagai byte aplikasi biasa.

State open-file dapat tetap dipakai bersama setelah transfer

Pada Linux, descriptor merujuk melalui tabel descriptor ke sebuah open file description. Objek kernel tersebut membawa state seperti posisi file saat ini dan file status flags. Descriptor yang diterima melalui SCM_RIGHTS merujuk open file description yang sama dengan descriptor yang dikirim, dalam arti yang sama dengan descriptor hasil dup().

Untuk regular file yang dapat di-seek, perubahan posisi melalui satu referensi dapat memengaruhi I/O berikutnya melalui referensi lain. Jika pengirim membaca 128 byte dan memajukan posisi bersama, penerima yang memakai descriptor hasil transfer dapat memulai dari posisi tersebut, kecuali positioned I/O atau seek eksplisit mengubah interaksi itu.

File status flags yang terkait dengan open file description juga dipakai bersama. Descriptor flags berbeda: state tersebut melekat pada entri tabel descriptor. Pemisahan ini sangat relevan untuk state close-on-exec.

Transfer tersebut tidak berarti posisi file independen atau status open-file independen. Perangkat lunak yang memerlukan state independen umumnya memerlukan open file description terpisah, sesuai semantik objek dan API yang tersedia.

Close-on-exec melekat pada descriptor penerima

FD_CLOEXEC adalah descriptor flag, bukan properti open file description yang dipakai bersama. Descriptor hasil transfer karena itu harus diperlakukan sebagai entri tabel descriptor baru dengan state close-on-exec sendiri.

Pada Linux, recvmsg() menerima MSG_CMSG_CLOEXEC. Ketika didukung dan diberikan, kernel menetapkan close-on-exec pada descriptor yang diterima melalui SCM_RIGHTS. Mekanisme ini menutup race yang dapat muncul saat kode multithread menerima descriptor lalu baru memanggil fcntl() untuk menetapkan FD_CLOEXEC: thread lain dapat mengeksekusi program baru pada interval tersebut.

Ini merupakan properti sinkronisasi pada level API, bukan sekadar flag praktis. Pemasangan descriptor secara atomik bersama state close-on-exec menentukan apakah execve() yang tidak terkait dapat mewarisi capability yang diterima.

Batas pesan dan ancillary data berada dalam satu operasi penerimaan

Transfer descriptor terkait dengan pesan socket, tetapi aplikasi tetap harus memvalidasi payload biasa dan control data yang dikembalikan oleh recvmsg(). Control buffer memiliki kapasitas terbatas. Jika ancillary data terpotong, MSG_CTRUNC dapat dilaporkan.

Kode penerima yang tangguh tidak dapat menganggap setiap control record sebagai SCM_RIGHTS. Kode perlu memeriksa cmsg_level, cmsg_type, dan panjang record sebelum mengambil nilai descriptor. Penerima juga memiliki descriptor yang berhasil dipasang dan harus menutup referensi yang tidak dipertahankan.

Payload biasa sering membawa metadata aplikasi yang menyatakan peran objek hasil transfer. Metadata tersebut bukan jaminan kernel mengenai tipe atau state descriptor. Jika protokol mensyaratkan socket, direktori, atau mode akses tertentu, penerima memerlukan strategi validasi yang sesuai dan tidak cukup mempercayai label dalam pesan.

Pengiriman descriptor mendelegasikan akses yang sudah ada

Handoff berbasis pathname meminta proses penerima me-resolve nama dan membuka objek dengan credential, tampilan namespace, serta kondisi waktu miliknya sendiri. Descriptor passing memindahkan referensi yang telah melewati pemeriksaan saat open, meskipun operasi selanjutnya tetap dapat memiliki pemeriksaan izin tersendiri.

Hal ini mengubah batas antarmuka. Broker dengan privilege dapat melakukan bind pada listening socket lalu mentransfernya ke service dengan privilege lebih rendah. Proses induk dapat membuat endpoint pipe dan hanya memberikan satu sisi. Sebuah proses dapat membuka direktori dengan aturan resolusi terkontrol lalu mentransfer referensi direktori tersebut tanpa meminta penerima mengulang traversal pathname.

Descriptor hasil transfer dengan demikian menjadi handle menyerupai capability menuju objek kernel, dibatasi oleh operasi yang diizinkan objek dan descriptor tersebut. SCM_RIGHTS tidak menyalin credential proses pengirim dan tidak memberikan akses arbitrer di luar referensi yang ditransfer.

Lifetime melampaui entri descriptor milik pengirim

Referensi kernel, bukan nomor descriptor, menentukan lifetime objek. Setelah transfer berhasil, menutup descriptor milik pengirim tidak membatalkan descriptor yang sudah dipasang pada penerima. Setiap entri descriptor memegang referensinya sendiri menuju open file description yang dipakai bersama.

Sebaliknya, descriptor yang tertahan tanpa sengaja dapat memperpanjang lifetime resource. Pipe tidak menampilkan end-of-file kepada reader selama referensi write-end masih terbuka di suatu tempat. Listening socket tetap memiliki referensi selama descriptor hasil transfer masih terpasang. Protokol descriptor passing karena itu memerlukan aturan ownership eksplisit untuk jalur sukses, penolakan, pemrosesan parsial, dan shutdown.

Ini juga menjadi alasan untuk segera menutup ancillary descriptor yang tidak diharapkan. Mengabaikan descriptor yang tidak diinginkan tanpa menutupnya bukan tindakan netral; referensi kernel tetap hidup.

Transfer mempertahankan batas objek, bukan maksud aplikasi

SCM_RIGHTS paling tepat ketika protokol memperlakukan ownership descriptor sebagai bagian dari model datanya. Kernel dapat mempertahankan referensi beserta semantik open-file melintasi batas proses, tetapi kernel tidak dapat mengodekan peran yang dimaksud aplikasi untuk referensi tersebut.

Penerima tetap harus menentukan tipe descriptor yang diterima, apakah offset atau status bersama sesuai, descriptor mana yang bertahan setelah eksekusi program berikutnya, serta kapan ownership berakhir. Keputusan tersebut berada di atas mekanisme transport.

Batas akhirnya bersifat tegas: ancillary data pada Unix domain socket mentransfer referensi berbasis kernel, tabel descriptor tetap lokal bagi proses, dan state open-file tertentu dapat tetap dipakai bersama. Desain yang menjaga pemisahan tersebut dapat mendelegasikan resource yang sudah terbentuk tanpa menganggap descriptor sekadar integer atau menganggap transfer menciptakan instance open yang independen.