Làm cách nào để đặt SGID trong PHP?

Oct 07 2020

Tôi không thể quản lý để đặt bit SGID từ PHP.

Tôi có thư mục này:

  4 drwxrwsr-x 12 www-data mygroup  4096 Oct  7 16:05 mydir

Lưu ý bit SGID. Vì vậy, nếu tôi chỉ cần tạo một thư mục vào nó từ shell với mkdir test, tôi nhận được

  4 drwxr-sr-x  2 myuser   mygroup   4096 Oct  7 16:22 test

Lưu ý rằng bit SGID được kế thừa. Nhưng tôi muốn nó nhóm có thể ghi (mà tôi umask 22không cho phép) để tôi có thể đơn giản chmod 02775 testvà tôi hoàn toàn hạnh phúc:

  4 drwxrwsr-x  2 myuser   mygroup   4096 Oct  7 16:22 test

Bây giờ tôi muốn làm điều tương tự từ một tập lệnh PHP. Đương nhiên, tôi mong đợi điều này sẽ hoạt động:

mkdir("/mydir/test2");
chmod("/mydir/test2", 02775);

Nhưng nó không xảy ra và tôi nhận được điều này thay thế (SGID được đặt lại):

  4 drwxrwxr-x  2 www-data mygroup   4096 Oct  7 16:30 test2

Dưới đây là một số thử nghiệm hữu ích khác:

mkdir("/mydir/test3");
mkdir("/mydir/test4");
passthru("chmod 02775 '/mydir/test4'");
mkdir("/mydir/test5");
passthru("chmod g+w '/mydir/test5'");

Kết quả là

  4 drwxr-sr-x  2 www-data mygroup   4096 Oct  7 16:39 test3
  4 drwxrwxr-x  2 www-data mygroup   4096 Oct  7 16:39 test4
  4 drwxrwxr-x  2 www-data mygroup   4096 Oct  7 17:06 test5

Điều thú vị là mkdir()một mình đã bảo toàn SGID, nhưng chmod()đặt lại nó, thậm chí thông qua passthru().

Tôi biết rằng hướng dẫn sử dụng PHP nói chmodrằng lệnh chỉ mong đợi ba chữ số bát phân, nhưng tôi cũng đã đọc câu hỏi về stackoverflow này và có vẻ như hướng dẫn này chứa thông tin lỗi thời và những thứ khác có thể ảnh hưởng đến SGID. Bên cạnh đó, nó không nên ảnh hưởng đến các passthru()phiên bản, phải không? Câu hỏi stackoverflow tương tự đề cập đến điều gì đó về việc chmod()cần phải là "người cuối cùng được gọi" sau chown()và chgrp(), nhưng tôi không sử dụng bất kỳ câu hỏi nào trong số đó.

Tôi đang làm gì sai?

Trả lời

DanielB Oct 08 2020 at 21:11

Điều này đang chạy trên một máy chủ web hay chỉ là một tập lệnh CLI? Nếu CLI, người dùng hay người chủ?

Ngoài ra, tại sao lại là thư mục? SGID được sử dụng trên các tệp chương trình, để cho phép người dùng chạy chương trình / tập lệnh với tư cách là người dùng khác, như "sudo". Bạn đã thử kiểm tra điều này trên các tệp thay vì thư mục chưa?

Paolo Oct 09 2020 at 12:37

Cuối cùng, cách duy nhất tôi có thể tìm để có được các quyền mà tôi cần là tận dụng hành vi chính xác của nó mkdir()và tránh việc gọi chmod()mà dường như đặt lại bit SGID bất kể điều gì. Cách duy nhất tôi có thể nghĩ để làm điều này là thay đổi umask bằng umask():

$myumask = umask(2); mkdir("/mydir/test6"); umask($myumask);

Điều này dường như hoạt động tốt:

  4 drwxrwsr-x  2 www-data mygroup   4096 Oct  9 14:22 test6

Điều này khiến tôi gặp vấn đề được nêu ra trong ghi chú của https://www.php.net/manual/en/function.umask.php: rằng tất cả các luồng của máy chủ web đa luồng chia sẻ cùng một umask , rõ ràng là dẫn đến hành vi không mong muốn và không thể đoán trước. May mắn thay, trong trường hợp của tôi, tôi có thể chắc chắn rằng tất cả các sáng tạo thư mục đều được thực hiện trong ngữ cảnh đơn luồng (về cơ bản, trong lần chạy thử nghiệm đầu tiên của một tập lệnh) và do đó tôi cảm thấy an toàn. Do đó, đây là một giải pháp hữu ích nhưng không phải là một giải pháp chung.