Apakah ada file yang selalu ada dan pengguna 'normal' tidak dapat menghapusnya?

14

Saya perlu ini untuk tes unit. Ada fungsi yang tidak lstat pada path file yang dilewatkan sebagai parameternya. Saya harus memicu jalur kode tempat lstatgagal (karena cakupan kode harus mencapai 90%)

Tes dapat berjalan hanya di bawah satu pengguna, oleh karena itu saya bertanya-tanya apakah ada file di Ubuntu yang selalu ada, tetapi pengguna normal tidak memiliki akses baca untuk itu, atau ke foldernya. (Jadi lstatakan gagal kecuali dieksekusi sebagai root.)

File yang tidak ada bukanlah solusi, karena ada jalur kode terpisah untuk itu, yang sudah saya picu.

EDIT: Kurangnya akses baca ke file saja tidak cukup. Dengan itu lstatmasih bisa dieksekusi. Saya dapat memicunya (pada mesin lokal saya, di mana saya memiliki akses root), dengan membuat folder di / root, dan file di dalamnya. Dan pengaturan izin 700 pada folder. Jadi saya mencari file yang ada di folder yang hanya dapat diakses oleh root.

Crouching Kitten
sumber
6
IMHO/etc/shadow
Romeo Ninov
3
Anda tidak dapat mengasumsikan keberadaan file apa pun, karena program Anda dapat berjalan di chroot atau namespace terpisah. Jika dengan anggapan bahwa / proc sudah di-mount adalah OK dan init tidak ada yang istimewa, maka /proc/1/fd/0harus dilakukan.
Mosvy
1
@mosvy Terima kasih yang bekerja pada mesin lokal saya. Hmm maka saya akan mencobanya di QA dan Staging pool juga.
Crouching Kitten
2
Mengapa Anda mengaitkan kode pengujian Anda dengan aroma OS tertentu padahal Anda hanya bisa membuat file sekali pakai dan menghapus akses baca Anda sendiri padanya?
Kilian Foth
4
Saya berpendapat bahwa itu bukan benar-benar unit test setelah mulai tergantung pada sistem file yang nyata, bukan mengejek.
Toby Speight

Jawaban:

21

Pada sistem Linux modern, Anda harus dapat menggunakan /proc/1/fdinfo/0(informasi untuk deskriptor file 1 (stdout) dari proses id 1 ( initdi root namespace pid yang seharusnya dijalankan sebagai root)).

Anda dapat menemukan daftar dengan (sebagai pengguna normal):

sudo find /etc /dev /sys /proc -type f -print0 |
  perl -l -0ne 'print unless lstat'

(hapus -type fjika Anda tidak ingin membatasi file biasa).

/var/cache/ldconfig/aux-cacheadalah kandidat potensial lain jika Anda hanya perlu mempertimbangkan sistem Ubuntu. Ini harus bekerja pada kebanyakan sistem GNU seperti /var/cache/ldconfigyang dibuat read + write + dapat dicari untuk root hanya dengan ldconfigperintah yang datang dengan libc GNU.

Stéphane Chazelas
sumber
1
Terima kasih! Jika /proc/1/fdinfo/0berfungsi di Ubuntu 16.04 dan 18.04, itu lebih dari cukup.
Crouching Kitten
1
Penggunaan /proc/1/fdinfo/0tidak selalu berfungsi dalam wadah (misalnya, wadah Docker), dan sering kali unit test dijalankan dalam wadah seperti itu di CI.
Philipp Wendler
@ Phippippendend, saya sudah menyebutkan namespace root pid . OP tidak bertanya tentang kontainer tetapi tentang file yang dijamin ada di tata letak sistem file sistem Ubuntu. Karena kontainer dapat berisi tata letak file dan direktori, pertanyaan itu tidak dapat dijawab di sana.
Stéphane Chazelas
12

Melihat halaman manual lstat (2) Anda bisa mendapatkan beberapa inspirasi pada kasus-kasus yang mungkin membuatnya gagal dengan kesalahan selain ENOENT (file tidak ada.)

Yang paling jelas adalah:

EACCES Izin pencarian ditolak untuk salah satu direktori di awalan jalur .

Jadi Anda memerlukan direktori yang tidak dapat Anda cari.

Ya, Anda dapat mencari yang sudah ada di sistem Anda (mungkin /var/lib/privatejika ada?) Tetapi Anda juga bisa membuatnya sendiri, dengan yang setara dengan:

$ mkdir myprivatedir
$ touch myprivatedir/myunreachablefile
$ chmod 0 myprivatedir
$ ls -l myprivatedir/myunreachablefile

Operasi lstat (2) akan gagal dengan EACCES di sini. (Menghapus semua izin dari direktori memastikan hal itu. Mungkin Anda bahkan tidak terlalu membutuhkannya dan chmod -xmenghapus izin eksekusi sudah cukup, karena mengeksekusi izin pada direktori diperlukan untuk mengakses file di bawahnya.)

Ada cara kreatif lain untuk membuat lstat (2) gagal, melihat halaman manualnya:

ENOTDIR Komponen awalan jalur path bukan direktori.

Jadi, mencoba mengakses file seperti /etc/passwd/nonexistentseharusnya memicu kesalahan ini, yang lagi berbeda dengan ENOENT ("Tidak ada file atau direktori") dan mungkin sesuai dengan kebutuhan Anda.

Yang lain adalah:

Jalur ENAMETOOLONG terlalu panjang.

Tetapi Anda mungkin perlu nama yang sangat panjang untuk yang ini (saya percaya 4.096 byte adalah batas tipikal, tetapi sistem / sistem file Anda mungkin memiliki yang lebih panjang.)

Akhirnya, sulit untuk mengatakan apakah semua ini benar - benar bermanfaat bagi Anda. Anda mengatakan Anda menginginkan sesuatu yang tidak memicu skenario "file tidak ada". Walaupun biasanya itu berarti kesalahan ENOENT, dalam praktiknya banyak pemeriksaan tingkat tinggi hanya akan menafsirkan kesalahan dari lstat (2) sebagai "tidak ada". Sebagai contoh test -eatau setara [ -e ...]dari shell mungkin hanya menafsirkan semua hal di atas sebagai "tidak ada", terutama karena tidak memiliki cara yang baik untuk mengembalikan pesan kesalahan yang berbeda dan tidak mengembalikan kesalahan akan menyiratkan file tersebut ada, yang pasti bukan itu masalahnya.

filbranden
sumber
@StephaneChazelas Poin bagus! Diperbarui.
filbranden
6

Anda bisa findmelakukannya sendiri.

Menggunakan /etc- direktori file konfigurasi sebagai titik awal:

sudo find /etc -type f -perm 0400 -user root

Di sistem saya, ini tidak mengembalikan apa pun.

Anda dapat menjadi kelompok yang tidak terlalu membatasi dan mengizinkan root(hanya pengguna yang rootharus menjadi anggota grup root), dan melihat keluar untuk izin 440:

sudo find /etc -perm 0440 -user root -group root

Di sistem saya ini mengembalikan:

/etc/sudoers.d/README
/etc/sudoers

Edit:

Berdasarkan hasil edit Anda, Anda mencari direktori yang tidak memiliki izin yang memadai bagi pengguna yang meminta untuk mencegah daftar direktori:

sudo find / -perm o-rwx -type d -user root -group root 

di sini saya mencari direktori ( -type d) yang tidak memiliki bit perm baca-tulis-eksekusi untuk yang lain ( o-rwx) dan dimiliki oleh root:root.

Secara teknis, tidak adanya xbit eksekusi ( ) akan mencegah daftar direktori ( lstat(2)) pada direktori.

Dalam output saya temukan /run/systemd/inaccessible/di sistem berbasis init Systemd saya.

Mengenai file dalam /proc, /sys, /dev:

  • Sistem file ini adalah virtual FS yaitu mereka berada di memori, bukan pada disk

  • Jika Anda berencana untuk mengandalkan /proc, gunakan /proc/1/yaitu mengandalkan sesuatu di bawah PID 1, bukan PID yang lebih baru untuk memiliki keandalan / konsistensi karena PID (proses) selanjutnya tidak dijamin ada.

heemayl
sumber
Terima kasih, saya pikir pertanyaan saya salah. Saya masih bisa lstat file tanpa akses baca ke mereka. Mungkin akses ke folder harus dibatasi? (Saya memodifikasi judulnya)
Crouching Kitten
Terima kasih. Dengan find / -type d -perm 0400 -user rootsaya telah menemukan direktori /proc/20/map_files/, jika saya merujuk ke nama file yang dibuat di dalam folder itu, seperti /proc/20/map_files/asdasd, maka selalu gagal. Apakah folder itu selalu ada di Ubuntu?
Crouching Kitten
@CrouchingKitten, direktori di /proc/1/mungkin lebih aman, karena init selalu ada. Tapi itu proc, bukan sistem file biasa, kalau-kalau itu penting.
ilkkachu
Terima kasih saya memberi suara positif, tetapi menerima jawaban yang lain, karena dia mengatakan itu dijamin yang /proc/1/fdinfo/0berfungsi pada Ubuntus modern.
Crouching Kitten
-perm o-rwxseperti -perm 0, bit semuanya dimulai dengan. Di sini, Anda ingin ! -perm -1.
Stéphane Chazelas