Vi có thể ghi vào tập tin mặc dù tập tin chỉ đọc


12

Ví dụ sau đây cho thấy cách tạo một tệp chỉ có quyền đọc. Như chúng ta có thể thấy, khi tôi cố gắng ghi vào tệp này bằng lệnh echo tôi nhận được , Permission denied.

Nhưng tại sao, trong trường hợp chúng ta sử dụng vi, chúng ta không nhận được Permission denied? Như có thể thấy ở đây, chúng ta có thể ghi vào tệp mặc dù tệp chỉ đọc.

Chuyện gì đang xảy ra ở đây? Đây có phải là một lỗi vi?

[admin@madona-machine1 ~]$ touch test-file
[admin@madona-machine1 ~]$ ls -ltr
total 0
-rw-r--r-- 1 admin admin 0 Apr 13 07:32 test-file
[admin@madona-machine1 ~]$ chmod -w  test-file
[admin@madona-machine1 ~]$ ls -ltr
total 0
-r--r--r-- 1 admin admin 0 Apr 13 07:32 test-file
[admin@madona-machine1 ~]$ echo try_to_write > test-file
-bash: test-file: Permission denied
[admin@madona-machine1 ~]$ vi test-file

I am good singer,

 ~
 ~
 ~
 ~
 ~
 ~
 ~                                                
   "test-file" 1L, 4C written

1
FYI có một trang web beta SE cho việc này - vi.stackexchange.com
Raystafarian

Câu trả lời:


28

Lưu ý : Vì lý do cấp phép cũ, hầu hết các bản phân phối GNU / Linux không bao gồm chương trình vi gốc như được viết bởi Bill Joy. Thay vào đó, lệnh vi được cung cấp bằng cách chạy Vim ở chế độ tương thích vi. Câu trả lời sau dựa trên việc chạy Vim với chế độ tương thích vi.

Sửa đổi tệp chỉ đọc

Vim cảnh báo người dùng nếu họ sửa đổi bộ đệm của tệp chỉ đọc , W10: Warning: Changing a readonly file. Nếu người dùng cố gắng ghi vào tệp này, họ sẽ nhận được thông báo lỗi sau 'readonly' option is set (add ! to override).

Khi thư mục mẹ có thể ghi bởi người dùng Vim

Vim, rất hữu ích, cho người dùng biết rằng họ có thể khăng khăng đòi viết bằng cách gắn thêm dấu chấm than !vào wlệnh. Nếu phiên bản mạnh mẽ này của lệnh ghi được sử dụng, Vim sẽ xóa tệp gốc (nếu sử dụng Vim với bộ backuptùy chọn chỉ Vim , tệp gốc thực sự được đổi tên thành giống như tệp sao lưu). Sau đó, nó sẽ mở (tạo) một tệp mớicùng tên với bản gốc và ghi nội dung của bộ đệm vào tệp mới này. Điều này có thể được quan sát bằng cách kiểm tra nút inode của tệp trước và sau khi chạy Vim:

$ ls -l --inode t

131529 -r--r--r-- 1 anthony anthony 0 Apr 13 09:23 t

$ vi t
$ ls -l --inode t

131649 -r--r--r-- 1 anthony anthony 4 Apr 13 09:23 t

Lưu ý: Điều này cũng có thể thay đổi quyền và quyền sở hữu tệp và ngắt liên kết (tượng trưng), ví dụ: nếu tệp gốc được sở hữu bởi người dùng khác, tệp mới sẽ thuộc sở hữu của người dùng đang chạy Vim.

Một quy trình chỉ có thể làm điều này nếu nó có quyền ghi cho thư mục mẹ của tệp. Nói chung, để đảm bảo rằng một chương trình không thể sửa đổi một tệp, các quyền của cả chính tệp đó và thư mục mẹ của nó phải được bảo mật.

Khi thư mục mẹ không thể ghi được bởi người dùng Vim

Tuy nhiên, ngay cả trong trường hợp này, Vim vẫn cố gắng hết sức để giúp người dùng khăng khăng ghi đè lên tệp. Nếu người dùng Vim có quyền sở hữu tệp, Vim có thể khắc phục hạn chế thư mục mẹ chỉ đọc bằng cách thay đổi tạm thời quyền của tệp (sử dụng lệnh chmodgọi hệ thống), ghi bộ đệm vào tệp, đóng tệp và sau đó thay đổi tệp quyền trở lại. Đây là một trích xuất của các cuộc gọi hệ thống được thực hiện trong khi chạy vi thông qua strace , strace -o ../vi.trace vi t:

getuid()                                = 501
chmod("t", 0100644)                     = 0
open("t", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "I am good singer,\n", 18)     = 18
fsync(4)                                = 0
close(4)                                = 0
chmod("t", 0100444)                     = 0

Lưu ý: Điều này không xảy ra nếu người dùng Vim đang chỉnh sửa một tệp mà họ không có quyền sở hữu vì Vim sẽ không thể thay đổi quyền của tệp.

Phụ lục

Để thực sự chắc chắn rằng một tệp không thể được sửa đổi (trên hệ thống GNU / Linux), hãy chạy chattrlệnh dưới dạng siêu người dùng:

sudo chattr +i filename

Từ man chattr:

Không thể sửa đổi tệp có thuộc tính 'i': không thể xóa hoặc đổi tên, không thể tạo liên kết đến tệp này và không có dữ liệu nào có thể được ghi vào tệp. Chỉ có siêu người dùng hoặc một quá trình sở hữu khả năng CAP_LINUX_IMMUTABLE mới có thể đặt hoặc xóa thuộc tính này.


2
Thánh khói, thật kỹ!
Camille Goudeseune

4
@CamilleGoudeseune Sau khi tôi đăng phiên bản đầu tiên cho câu trả lời của mình, tôi đã thực hiện một số thử nghiệm và cuối cùng đã dành khoảng một giờ để chạy Vim qua strace để xem những gì nó đang diễn ra trong hậu trường trong các tình huống khác nhau (các hoán vị khác nhau của quyền và quyền sở hữu của cả hai tệp và thư mục mẹ). Đôi khi tôi bị mang đi nhưng một khi tôi đã công bố một câu trả lời, tôi muốn chắc chắn rằng những gì tôi đang nói là chính xác.
Anthony Geoghegan

5

Hầu hết nếu không phải tất cả vitriển khai ngăn cản bạn để ghi các file nếu bạn sử dụng thường xuyên tiết kiệm lệnh như một trong hai ZZ, :w, :wqhay :x, ví dụ như với vim:

:w
E45: 'readonly' option is set (add ! to override)

Mặt khác, nếu bạn yêu vicầu ghi tệp bất chấp quyền của nó, bằng cách sử dụng một cái gì đó như :x!hoặc :wq!, trình soạn thảo đang tạm thời thư giãn các quyền để cho phép tệp được ghi:

...
stat("test-file", {st_mode=S_IFREG|0444, st_size=7, ...}) = 0
getuid()                                = 1000
chmod("test-file", 0100644)             = 0
...
open("test-file", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "I am good singer,\n", 18)               = 18
fsync(4)                                = 0
close(4)                                = 0
chmod("test-file", 0100444)             = 0
....

Trong trường hợp đó, số inode không thay đổi.

Cuối cùng, đây không phải là một lỗi vì nếu bạn không được phép thay đổi quyền truy cập tệp, bạn không thể sửa đổi nó thông qua vi.


Hừ! Sau khi tôi đăng câu trả lời của mình, tôi đã thực hiện một số thử nghiệm và cuối cùng đã dành gần một giờ để chạy Vim qua strace để xem những gì nó đang làm đằng sau hậu trường trong các tình huống khác nhau (các hoán vị khác nhau của quyền và quyền sở hữu của cả tệp và thư mục mẹ). Tôi chỉ thấy câu trả lời của bạn sau khi tôi hoàn thành việc tóm tắt kết quả thí nghiệm của mình. Đó là một kinh nghiệm học tập tốt.
Anthony Geoghegan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.