Saya adalah root. Saya ingin tahu apakah pengguna non-root memiliki akses tulis ke beberapa file - ribuan di antaranya. Bagaimana melakukannya secara efisien sambil menghindari proses pembuatan?
shell
files
permissions
users
Howard
sumber
sumber
access(2)
dengan UID nyata yang diatur dengan tepat (mis. Viasetresuid(2)
atau setara portabel)? Maksudku, aku akan kesulitan melakukan itu dari bash, tapi aku yakin Perl / Python bisa mengatasinya.[ -w
biasanya menggunakan akses (2) atau setara. Anda juga perlu mengatur gids di samping uid (seperti su atau sudo do). bash tidak memiliki dukungan bawaan untuk itu tetapi zsh melakukannya.chgrp
shell apa pun.Jawaban:
Mungkin seperti ini:
Di atas menjalankan program eksternal tunggal untuk setiap file, yaitu
stat(1)
.Catatan: Ini mengasumsikan
bash(1)
, dan inkarnasi Linux daristat(1)
.Catatan 2: Silakan baca komentar dari Stéphane Chazelas di bawah ini untuk masa lalu, sekarang, masa depan, dan potensi bahaya dan keterbatasan dari pendekatan ini.
sumber
-
. Anda dapat memodifikasinya untuk menerima daftar yang dibatasi NUL sebagai gantinya denganread -d ''
util-linux
) yang secara khusus ditulis untuk Linux, yangstat
Anda maksud bukan, itu adalah perintah GNU yang telah porting ke sebagian besar sistem, tidak hanya Linux. Perhatikan juga bahwa Anda memilikistat
perintah di Linux jauh sebelum GNUstat
ditulis (stat
zsh builtin).stat(1)
". Saya mengacu padastat(1)
yang menerima-c <format>
sintaks, yang bertentangan dengan, katakanlah, sintaks BSD-f <format>
. Saya juga percaya itu cukup jelas saya tidak merujukstat(2)
. Saya yakin halaman wiki tentang sejarah perintah umum akan sangat menarik.TL; DR
Anda perlu menanyakan sistem apakah pengguna memiliki izin menulis. Satu-satunya cara yang dapat diandalkan adalah untuk mengganti gid yang efektif, gid dan suplementasi yang efektif menjadi milik pengguna dan menggunakannya
access(W_OK)
panggilan sistem (bahkan yang memiliki beberapa keterbatasan pada beberapa sistem / konfigurasi).Dan ingatlah bahwa tidak memiliki izin menulis ke file tidak selalu menjamin bahwa Anda tidak dapat mengubah konten file di jalur itu.
Cerita yang lebih panjang
Mari kita pertimbangkan apa yang diperlukan misalnya bagi $ user untuk memiliki akses tulis
/foo/file.txt
(dengan asumsi tidak ada/foo
dan/foo/file.txt
merupakan symlink)?Dia membutuhkan:
/
(tidak perluread
)/foo
(tidak perluread
)/foo/file.txt
Anda sudah dapat melihat bahwa pendekatan (seperti @ lcd047 atau @ apaul ) yang memeriksa hanya izin
file.txt
tidak akan berfungsi karena mereka bisa mengatakanfile.txt
itu dapat ditulisi bahkan jika pengguna tidak memiliki izin pencarian untuk/
atau/foo
.Dan pendekatan seperti:
Tidak akan berfungsi karena itu tidak akan melaporkan file dalam direktori pengguna tidak memiliki akses baca (
find
berjalan karena$user
tidak dapat membuat daftar konten mereka) bahkan jika ia dapat menulis kepada mereka.Jika kita melupakan ACL, sistem file read-only, flag FS (seperti immutable), langkah-langkah keamanan lainnya (apparmor, SELinux, yang bahkan dapat membedakan antara berbagai jenis penulisan) dan hanya fokus pada izin tradisional dan atribut kepemilikan, untuk mendapatkan diberikan (cari atau tulis) izin, itu sudah cukup rumit dan sulit untuk diungkapkan
find
.Anda membutuhkan:
Dalam
find
sintaksis, di sini sebagai contoh dengan pengguna uid 1 dan gids 1 dan 2, yaitu:Yang itu memangkas direktori yang pengguna tidak memiliki hak untuk mencari dan untuk jenis file lainnya (symlink dikecualikan karena tidak relevan), memeriksa akses tulis.
Jika Anda juga ingin mempertimbangkan akses tulis ke direktori:
Atau untuk arbitrer
$user
dan keanggotaan grupnya diambil dari basis data pengguna:(total 3 proses::
id
,sed
danfind
)Yang terbaik di sini adalah untuk turun pohon sebagai root dan memeriksa izin sebagai pengguna untuk setiap file.
(Itu satu
find
proses ditambah satusudo
dansh
proses setiap beberapa ribu file,[
danprintf
biasanya dibangun di shell).Atau dengan
perl
:(3 proses secara total:
find
,sudo
danperl
).Atau dengan
zsh
:(0 total proses, tetapi menyimpan seluruh daftar file dalam memori)
Solusi tersebut bergantung pada
access(2)
panggilan sistem. Itu alih-alih mereproduksi algoritma yang digunakan sistem untuk memeriksa izin akses, kami meminta sistem untuk melakukan pemeriksaan dengan algoritma yang sama (yang memperhitungkan izin akun, ACL, bendera yang tidak dapat diubah, sistem file read-only ... ) itu akan digunakan jika Anda mencoba untuk membuka file untuk menulis, jadi terdekat Anda akan mendapatkan solusi yang dapat diandalkan.Untuk menguji solusi yang diberikan di sini, dengan berbagai kombinasi pengguna, grup, dan izin, Anda dapat melakukan:
Memvariasikan pengguna antara 1 dan 2 dan grup antara 1, 2, dan 3 dan membatasi diri hingga 9 bit yang lebih rendah dari izin karena sudah 9458694 file dibuat. Itu untuk direktori dan sekali lagi untuk file.
Itu menciptakan semua kemungkinan kombinasi
u<x>g<y>/<mode1>/u<z>g<w>/<mode2>
. Pengguna dengan uid 1 dan gids 1 dan 2 akan memiliki akses tulis,u2g1/010/u2g3/777
tetapi tidaku1g2/677/u1g1/777
misalnya.Sekarang, semua solusi itu mencoba mengidentifikasi jalur file yang dapat dibuka oleh pengguna untuk ditulis, itu berbeda dari jalur di mana pengguna mungkin dapat mengubah konten. Untuk menjawab pertanyaan yang lebih umum itu, ada beberapa hal yang harus diperhatikan:
/a/b/file
tetapi jika ia memilikifile
(dan memiliki akses pencarian/a/b
, dan sistem file tidak hanya-baca, dan file tidak memiliki bendera yang tidak dapat diubah, dan ia memiliki akses shell ke sistem), maka dia akan dapat mengubah izinfile
dan memberikan dirinya akses./a/b
tetapi tidak memiliki akses pencarian untuk itu./a/b/file
karena ia tidak memiliki akses pencarian ke/a
atau/a/b
, tetapi file itu mungkin memiliki hard link/b/c/file
, misalnya, dalam hal ini ia mungkin dapat memodifikasi konten/a/b/file
dengan membukanya melalui/b/c/file
jalurnya./a
, tetapi/a/b
dapat di -mount- in/c
, sehingga dia dapat membukafile
untuk menulis melalui/c/file
jalur lainnya./a/b/file
, tetapi jika dia memiliki akses tulis untuk/a/b
dia dapat menghapus atau mengganti namafile
di sana dan menggantinya dengan versinya sendiri. Dia akan mengubah konten file/a/b/file
bahkan jika itu akan menjadi file yang berbeda./a
(dia bisa mengganti nama/a/b
menjadi/a/c
, membuat/a/b
direktori baru dan barufile
di dalamnya.Untuk menemukan jalur yang
$user
akan dapat dimodifikasi. Untuk mengatasi 1 atau 2, kita tidak bisa lagi mengandalkanaccess(2)
panggilan sistem. Kami dapat menyesuaikanfind -perm
pendekatan kami untuk menganggap akses pencarian ke direktori, atau menulis akses ke file segera setelah Anda pemiliknya:Kita dapat mengatasi 3 dan 4, dengan merekam perangkat dan nomor inode atau semua file $ user memiliki izin menulis dan melaporkan semua path file yang memiliki nomor dev + inode tersebut. Kali ini, kita bisa menggunakan yang lebih andal
access(2)
pendekatan berbasis :Sesuatu seperti:
5 dan 6 pada pandangan pertama diperumit dengan
t
sedikit izin. Ketika diterapkan pada direktori, itu adalah bit penghapusan terbatas yang mencegah pengguna (selain pemilik direktori) menghapus atau mengganti nama file yang tidak mereka miliki (walaupun mereka memiliki akses tulis ke direktori).Misalnya, jika kita kembali ke contoh kita sebelumnya, jika Anda memiliki akses tulis ke
/a
, maka Anda harus dapat mengubah nama/a/b
untuk/a/c
, dan kemudian menciptakan sebuah/a/b
direktori dan barufile
di sana. Tetapi jikat
bit sudah diaktifkan/a
dan Anda tidak memiliki/a
, maka Anda hanya dapat melakukannya jika Anda memilikinya/a/b
. Itu memberi:t
bit tidak disetel, dan Anda berada dalam kasus yang sama seperti di atas (semua jalur file adalah milik Anda).Jadi kita dapat mengatasi semua 1, 2, 5 dan 6 dengan:
Itu dan solusi untuk 3 dan 4 adalah independen, Anda dapat menggabungkan output mereka untuk mendapatkan daftar lengkap:
Sebagaimana harus jelas jika Anda telah membaca semuanya sejauh ini, sebagian darinya setidaknya hanya berkaitan dengan izin dan kepemilikan, bukan fitur lain yang dapat memberikan atau membatasi akses tulis (hanya baca FS, ACL, bendera tidak berubah, fitur keamanan lainnya ...). Dan ketika kami memprosesnya dalam beberapa tahap, beberapa informasi itu mungkin salah jika file / direktori sedang dibuat / dihapus / diubah namanya atau izin / kepemilikannya dimodifikasi ketika skrip sedang berjalan, seperti pada server file yang sibuk dengan jutaan file .
Catatan portabilitas
Semua kode itu standar (POSIX, Unix for
t
bit) kecuali:-print0
adalah ekstensi GNU sekarang juga didukung oleh beberapa implementasi lainnya. Denganfind
implementasi yang tidak memiliki dukungan untuk itu, Anda dapat menggunakan-exec printf '%s\0' {} +
sebagai gantinya, dan mengganti-exec sh -c 'exec find "$@" -print0' sh {} +
dengan-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
.perl
bukan perintah yang ditentukan POSIX tetapi tersedia secara luas. Anda perluperl-5.6.0
atau di atas-Mfiletest=access
.zsh
bukan perintah yang ditentukan POSIX. Ituzsh
kode di atas harus bekerja dengan zsh-3 (1995) dan di atas.sudo
bukan perintah yang ditentukan POSIX. Kode harus bekerja dengan versi apa pun selama konfigurasi sistem memungkinkan berjalanperl
sebagai pengguna yang diberikan.sumber
x
izin pencarian ( bit) pada direktori. Anda juga dapat memiliki izin pencarian tetapi tidak membaca , artinya file di sana disembunyikan untuk Anda, tetapi jika Anda tahu namanya, Anda dapat mengaksesnya. Contoh tipikal adalah direktori file sesi php (sesuatu seperti / var / lib / php).Anda dapat menggabungkan opsi dengan
find
perintah, sehingga akan menemukan file dengan mode dan pemilik yang ditentukan. Contohnya:Perintah di atas akan mencantumkan semua entri yang termasuk dalam grup "staf" atau "pengguna" dan memiliki izin menulis untuk grup itu.
Anda juga harus memeriksa entri yang dimiliki oleh pengguna Anda, dan file yang dapat ditulisi dunia, jadi:
Namun, perintah ini tidak akan cocok dengan entri dengan ACL yang diperluas. Jadi, Anda dapat
su
menemukan semua entri yang dapat ditulis:sumber
r-xrwxrwx yourusername:anygroup
ataur-xr-xrwx anyone:staff
dapat ditulisi.yourusername
tidak memiliki akses.Pendekatannya tergantung pada apa yang sebenarnya Anda uji.
Ini karena ada begitu banyak cara untuk sampai pada angka 2) dan jawaban Stéphane mencakup semua ini dengan baik (tidak dapat diubah adalah untuk mengingat), dan ingat bahwa ada cara fisik juga, seperti melepas drive atau membuatnya hanya-baca di sebuah tingkat perangkat keras (tab floppy). Saya menduga ribuan file Anda berada di direktori yang berbeda dan Anda menginginkan laporan atau Anda memeriksa daftar master. (Lain penyalahgunaan Wayang hanya menunggu untuk terjadi).
Anda mungkin ingin Stéphane's perl tree-traversal dan untuk "bergabung" dengan daftar jika diperlukan (su juga akan menangkap eksekusi yang hilang pada direktori induk?). Jika surrogacy adalah masalah kinerja, apakah Anda melakukan ini untuk "sejumlah besar" pengguna? Atau apakah ini permintaan online? Jika ini merupakan persyaratan permanen yang berkelanjutan, mungkin sudah saatnya untuk mempertimbangkan produk pihak ketiga.
sumber
Anda dapat melakukan...
... untuk daftar semua file yang pengguna tidak dapat menulis sebagaimana ditulis ke stderr dalam formulir ...
... atau serupa.
Lihat komentar di bawah ini untuk catatan tentang masalah yang mungkin dimiliki pendekatan ini, dan penjelasan di bawah untuk alasan mengapa hal itu mungkin berhasil. Lebih waras lagi, Anda mungkin hanya perlu
find
file biasa seperti:Singkatnya,
tee
akan mencetak kesalahan ketika mencoba keopen()
file dengan salah satu dari dua bendera ...... dan bertemu ...
... sebagaimana ditentukan di sini :
Karena itu harus memeriksa dengan cara yang sama
test -w
tidak ...Mereka berdua memeriksa EACCESS .
sumber
tee
akan menggantung kecuali secara eksplisit terputus satu kali per menjalankan. Itu adalah hal terdekat yang bisa saya pikirkan[ -w
... meskipun - efeknya harus dekat karena itu menjamin pengguna dapat MENGUNGKAPKAN file. Jauh lebih mudah daripada opsi mana punpax
dengan-o
opsi format dan / atau-t
untuk mengecekEACCESS
- tetapi setiap kali saya menyarankanpax
orang tampaknya mengabaikannya. Dan, bagaimanapun, satu-satunya yangpax
saya temukan yang memenuhi std ada AST - dalam hal ini Anda mungkin juga menggunakan merekals
.