ค้นหาไฟล์ที่ผู้ใช้สามารถเขียนได้อย่างมีประสิทธิภาพด้วยการสร้างกระบวนการน้อยที่สุด


20

ฉันรูต ฉันต้องการทราบว่าผู้ใช้ที่ไม่ใช่รูทมีสิทธิ์ในการเขียนไฟล์บางไฟล์หรือไม่ - หลายพันไฟล์ จะทำอย่างมีประสิทธิภาพในขณะที่หลีกเลี่ยงการสร้างกระบวนการได้อย่างไร


โปรดแสดงให้เราเห็นว่าคุณทำอะไรจริง!
F. Hauri

คำถามแบบเดียวกันกับunix.stackexchange.com/a/88591
Stéphane Chazelas

สมมติว่าคุณไม่สนใจเกี่ยวกับสภาพการแข่งขันทำไมไม่เพียงแค่โทรหาaccess(2)UID ที่ตั้งค่าไว้อย่างเหมาะสม (เช่นผ่านsetresuid(2)หรือแบบพกพาที่เทียบเท่า) ฉันหมายความว่าฉันจะกดยากที่จะทำเช่นนั้นจากการทุบตี แต่ฉันแน่ใจว่า Perl / Python สามารถจัดการกับมันได้
Kevin

1
@Kevin [ -wโดยปกติแล้วเชลล์ใช้การเข้าถึง (2) หรือเทียบเท่า คุณต้องตั้งค่า gids เพิ่มเติมจาก uid (เช่น su หรือ sudo do) ทุบตีไม่ได้มีการสนับสนุนในตัว แต่ zsh ทำ
Stéphane Chazelas

@ StéphaneChazelas - คุณสามารถใช้งานได้chgrpในทุกเชลล์
mikeserv

คำตอบ:


2

อาจจะเป็นเช่นนี้:

#! /bin/bash

writable()
{
    local uid="$1"
    local gids="$2"
    local ids
    local perms

    ids=($( stat -L -c '%u %g %a' -- "$3" ))
    perms="0${ids[2]}"

    if [[ ${ids[0]} -eq $uid ]]; then
        return $(( ( perms & 0200 ) == 0 ))
    elif [[ $gids =~ (^|[[:space:]])"${ids[1]}"($|[[:space:]]) ]]; then
        return $(( ( perms & 020 ) == 0 ))
    else
        return $(( ( perms & 2 ) == 0 ))
    fi
}

user=foo
uid="$( id -u "$user" )"
gids="$( id -G "$user" )"

while IFS= read -r f; do
    writable "$uid" "$gids" "$f" && printf '%s writable\n' "$f"
done

stat(1)ดังกล่าวข้างต้นวิ่งโปรแกรมภายนอกเดียวสำหรับแต่ละไฟล์คือ

หมายเหตุ:นี้อนุมานและชาติลินุกซ์bash(1)stat(1)

หมายเหตุ 2:โปรดอ่านความคิดเห็นจากStéphane Chazelas ด้านล่างสำหรับอดีตปัจจุบันอนาคตและอันตรายที่อาจเกิดขึ้นและข้อ จำกัด ของวิธีการนี้


อาจกล่าวได้ว่าไฟล์นั้นเขียนได้แม้ว่าผู้ใช้จะไม่สามารถเข้าถึงไดเรกทอรีได้
Stéphane Chazelas

ที่ถือว่าชื่อไฟล์ที่ไม่ได้มีตัวอักษรและไฟล์ขึ้นบรรทัดใหม่เส้นทางผ่านใน stdin -ไม่ได้เริ่มต้นด้วย คุณสามารถแก้ไขได้เพื่อยอมรับรายการที่คั่นด้วย NUL แทนด้วยread -d ''
Stéphane Chazelas

โปรดทราบว่าไม่มีสิ่งดังกล่าวเป็นสถิติลินุกซ์ Linux เป็นเคอร์เนลที่พบในระบบ GNU และไม่ใช่ GNU ในขณะที่มีคำสั่ง (เช่นจากutil-linux) ที่เขียนขึ้นเป็นพิเศษสำหรับ Linux แต่statคุณกำลังอ้างถึงไม่ใช่คำสั่ง GNU ซึ่งได้รับการย้ายระบบไปยังระบบส่วนใหญ่ไม่ใช่เฉพาะ Linux โปรดทราบด้วยว่าคุณมีstatคำสั่งบน Linux มานานก่อนที่จะstatเขียนGNU ( statzsh builtin)
Stéphane Chazelas

2
@ Stéphane Chazelas: โปรดทราบว่าไม่มีสิ่งใดใน stat Linux - ฉันเชื่อว่าฉันเขียนว่า "การจุติของลินุกซ์stat(1)" ฉันหมายถึงstat(1)ว่ายอมรับ-c <format>ไวยากรณ์เมื่อเทียบกับการพูด, -f <format>ไวยากรณ์ stat(2)ฉันยังเชื่อว่ามันก็สวยใสผมไม่ได้หมายถึง ฉันแน่ใจว่าหน้าวิกิเกี่ยวกับประวัติของคำสั่งทั่วไปน่าสนใจทีเดียว
lcd047

1
@ Stéphane Chazelas: พูดได้ว่าไฟล์นั้นเขียนได้แม้ว่าผู้ใช้จะไม่สามารถเข้าถึงไดเรคทอรีที่มันอยู่ - จริงและอาจเป็นข้อ จำกัด ที่สมเหตุสมผล สมมติว่าชื่อไฟล์ไม่มีอักขระขึ้นบรรทัดใหม่ - จริงและอาจเป็นข้อ จำกัด ที่สมเหตุสมผล และเส้นทางของไฟล์ที่ส่งผ่านไปยัง stdin ไม่ได้ขึ้นต้นด้วย - - แก้ไขขอบคุณ
lcd047

17

TL; DR

find / ! -type l -print0 |
  sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -w'

คุณต้องถามระบบว่าผู้ใช้มีสิทธิ์ในการเขียนหรือไม่ วิธีที่น่าเชื่อถือเพียงวิธีเดียวคือการเปลี่ยน uid ที่มีประสิทธิภาพ, gid ที่มีประสิทธิภาพและการเสริม gids เป็นของผู้ใช้และใช้การaccess(W_OK)เรียกของระบบ (แม้จะมีข้อ จำกัด บางอย่างในบางระบบ / การกำหนดค่า)

และจำไว้ว่าการไม่มีสิทธิ์ในการเขียนลงไฟล์ไม่ได้รับประกันว่าคุณจะไม่สามารถแก้ไขเนื้อหาของไฟล์ที่พา ธ นั้นได้

เรื่องราวอีกต่อไป

ลองพิจารณาสิ่งที่ต้องทำเพื่อให้ผู้ใช้ $ มีสิทธิ์เข้าถึงการเขียน/foo/file.txt(สมมติว่าไม่มีเลย/fooและ/foo/file.txtเป็น symlink)

เขาต้องการ:

  1. ค้นหาการเข้าถึง/(ไม่จำเป็นread)
  2. ค้นหาการเข้าถึง/foo(ไม่จำเป็นread)
  3. การเข้าถึงเพื่อเขียน/foo/file.txt

คุณสามารถมองเห็นแล้วว่าวิธีการ (เช่น@ lcd047 ของหรือ@ apaul ของ ) ที่ตรวจสอบเพียงได้รับอนุญาตจากfile.txtจะไม่ทำงานเพราะพวกเขาอาจจะบอกว่าfile.txtสามารถเขียนได้แม้ว่าผู้ใช้จะไม่ได้รับอนุญาตการค้นหาหรือ//foo

และวิธีการเช่น:

sudo -u "$user" find / -writeble

จะไม่ทำงานเพราะจะไม่รายงานไฟล์ในไดเรกทอรีที่ผู้ใช้ไม่มีการเข้าถึงแบบอ่าน ( findทำงานเป็น$userไม่สามารถแสดงรายการเนื้อหาของพวกเขา) แม้ว่าเขาจะสามารถเขียนถึงพวกเขา

หากเราลืมเกี่ยวกับ ACLs ระบบไฟล์แบบอ่านอย่างเดียวแฟล็ก FS (เช่นไม่เปลี่ยนรูป) มาตรการรักษาความปลอดภัยอื่น ๆ (apparmor, SELinux ซึ่งสามารถแยกแยะความแตกต่างระหว่างการเขียนประเภทต่าง ๆ ) และเน้นเฉพาะการอนุญาตแบบดั้งเดิมและคุณสมบัติการเป็นเจ้าของเท่านั้น ที่กำหนด (ค้นหาหรือเขียน) findได้รับอนุญาตที่มีอยู่แล้วค่อนข้างซับซ้อนและยากที่จะแสดงด้วย

คุณต้องการ:

  • ถ้าคุณเป็นเจ้าของไฟล์คุณต้องได้รับอนุญาตจากเจ้าของ (หรือมี uid 0)
  • หากคุณไม่ได้เป็นเจ้าของไฟล์ แต่เป็นกลุ่มของคุณคุณต้องได้รับอนุญาตจากกลุ่มนั้น (หรือมี uid 0)
  • หากคุณไม่ได้เป็นเจ้าของและไม่อยู่ในกลุ่มใด ๆ ของคุณการอนุญาตอื่น ๆ จะมีผล (เว้นแต่ว่าคุณจะเป็น 0)

ในfindไวยากรณ์นี่เป็นตัวอย่างกับผู้ใช้ uid 1 และ gids 1 และ 2 นั่นคือ:

find / -type d \
  \( \
    -user 1 \( -perm -u=x -o -prune \) -o \
    \( -group 1 -o -group 2 \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) -o -type l -o \
    -user 1 \( ! -perm -u=w -o -print \) -o \
    \( -group 1 -o -group 2 \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

หนึ่งในนั้นพรุนไดเรกทอรีที่ผู้ใช้ไม่มีสิทธิ์ในการค้นหาและสำหรับไฟล์ประเภทอื่น ๆ (ยกเว้น symlinks ที่ไม่เกี่ยวข้อง) ตรวจสอบการเข้าถึงการเขียน

หากคุณต้องการพิจารณาสิทธิ์ในการเขียนในไดเรกทอรี:

find / -type d \
  \( \
    -user 1 \( -perm -u=x -o -prune \) -o \
    \( -group 1 -o -group 2 \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user 1 \( ! -perm -u=w -o -print \) -o \
    \( -group 1 -o -group 2 \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

หรือโดยพลการ$userและความเป็นสมาชิกกลุ่มที่ดึงมาจากฐานข้อมูลผู้ใช้:

groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
  \( \
    -user "$user" \( -perm -u=x -o -prune \) -o \
    \( -group $groups \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user "$user" \( ! -perm -u=w -o -print \) -o \
    \( -group $groups \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

(นั่นคือกระบวนการทั้งหมด 3 กระบวนการ: id, sedและfind)

สิ่งที่ดีที่สุดที่นี่คือการสืบทอดต้นไม้เป็นรูทและตรวจสอบการอนุญาตในฐานะผู้ใช้สำหรับแต่ละไฟล์

 find / ! -type l -exec sudo -u "$user" sh -c '
   for file do
     [ -w "$file" ] && printf "%s\n" "$file"
   done' sh {} +

(นั่นคือหนึ่งfindกระบวนการบวกหนึ่งsudoและshประมวลผลทุกๆสองสามพันไฟล์[และprintfมักจะสร้างขึ้นในเชลล์)

หรือด้วยperl:

find / ! -type l -print0 |
  sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -w'

(3 กระบวนการทั้งหมด: find, sudoและperl)

หรือด้วยzsh:

files=(/**/*(D^@))
USERNAME=$user
for f ($files) {
  [ -w $f ] && print -r -- $f
}

(0 กระบวนการทั้งหมด แต่เก็บรายการไฟล์ทั้งหมดไว้ในหน่วยความจำ)

โซลูชันเหล่านั้นขึ้นอยู่กับการaccess(2)เรียกใช้ระบบ นั่นคือแทนที่จะทำซ้ำอัลกอริทึมที่ระบบใช้ในการตรวจสอบการอนุญาตการเข้าถึงเราขอให้ระบบทำการตรวจสอบด้วยอัลกอริทึมเดียวกัน (ซึ่งคำนึงถึงการอนุญาตบัญชี ACLs ค่าสถานะที่ไม่เปลี่ยนรูปแบบระบบไฟล์แบบอ่านอย่างเดียว ... ) มันจะใช้หากคุณพยายามเปิดไฟล์เพื่อเขียนดังนั้นสิ่งที่ใกล้เคียงที่สุดที่คุณจะได้รับคือโซลูชันที่น่าเชื่อถือ

ในการทดสอบโซลูชันที่ให้ไว้ที่นี่ด้วยการผสมผสานระหว่างผู้ใช้กลุ่มและการอนุญาตต่าง ๆ คุณสามารถทำได้:

perl -e '
  for $u (1,2) {
    for $g (1,2,3) {
      $d1="u${u}g$g"; mkdir$d1;
      for $m (0..511) {
        $d2=$d1.sprintf"/%03o",$m; mkdir $d2; chown $u, $g, $d2; chmod $m,$d2;
        for $uu (1,2) {
          for $gg (1,2,3) {
            $d3="$d2/u${uu}g$gg"; mkdir $d3;
            for $mm (0..511) {
              $f=$d3.sprintf"/%03o",$mm;
              open F, ">","$f"; close F;
              chown $uu, $gg, $f; chmod $mm, $f
            }
          }
        }
      }
    }
  }'

การเปลี่ยนแปลงผู้ใช้ระหว่าง 1 ถึง 2 และกลุ่ม betweem 1, 2 และ 3 และ จำกัด ตัวเราไว้ที่ระดับต่ำกว่า 9 บิตของการอนุญาตเนื่องจากมันสร้างไฟล์แล้ว 9458694 สำหรับไดเรกทอรีและจากนั้นอีกครั้งสำหรับไฟล์

u<x>g<y>/<mode1>/u<z>g<w>/<mode2>ที่สร้างผสมเป็นไปได้ทั้งหมด ผู้ใช้ที่มี uid 1 และ gids 1 และ 2 จะมีสิทธิ์เข้าถึงเพื่อเขียนu2g1/010/u2g3/777แต่ไม่ใช่u1g2/677/u1g1/777สำหรับอินสแตนซ์

ตอนนี้โซลูชันเหล่านั้นพยายามระบุพา ธ ของไฟล์ที่ผู้ใช้อาจเปิดสำหรับการเขียนซึ่งแตกต่างจากพา ธ ที่ผู้ใช้อาจสามารถแก้ไขเนื้อหาได้ เพื่อตอบคำถามทั่วไปที่มากกว่านั้นมีหลายสิ่งที่ต้องคำนึงถึง:

  1. ผู้ใช้ $ อาจไม่สามารถเข้าถึงการเขียน/a/b/fileแต่ถ้าเขาเป็นเจ้าของfile(และมีการเข้าถึงการค้นหา/a/bและระบบไฟล์ไม่ได้เป็นแบบอ่านอย่างเดียวและไฟล์ไม่มีการตั้งค่าไม่เปลี่ยนรูปและเขาได้เข้าถึงเชลล์ไปยังระบบ) จากนั้นเขาจะสามารถเปลี่ยนการอนุญาตของfileและอนุญาตการเข้าถึงของตนเอง
  2. สิ่งเดียวกันถ้าเขาเป็นเจ้าของ/a/bแต่ไม่มีการเข้าถึงการค้นหา
  3. ผู้ใช้ $ อาจไม่สามารถเข้าถึงได้/a/b/fileเนื่องจากเขาไม่มีสิทธิ์เข้าถึงการค้นหา/aหรือ/a/bแต่ไฟล์นั้นอาจมีฮาร์ดลิงก์/b/c/fileในกรณีนี้เขาอาจสามารถแก้ไขเนื้อหาของ/a/b/fileโดยเปิดผ่าน/b/c/fileเส้นทาง
  4. สิ่งเดียวกันกับผูกม้า เขาอาจไม่สามารถเข้าถึงการค้นหา/aแต่/a/bอาจเชื่อมโยงเข้า/cด้วยกันเพื่อให้เขาสามารถเปิดfileเพื่อเขียนผ่าน/c/fileเส้นทางอื่น
  5. เขาอาจไม่มีสิทธิ์เขียน/a/b/fileแต่ถ้าเขามีสิทธิ์เข้าถึงเพื่อเขียน/a/bสามารถลบหรือเปลี่ยนชื่อfileในนั้นและแทนที่ด้วยเวอร์ชันของเขาเอง เขาจะเปลี่ยนเนื้อหาของไฟล์/a/b/fileแม้ว่าจะเป็นไฟล์อื่น
  6. สิ่งเดียวกันถ้าเขามีการเขียนการเข้าถึง/a(เขาสามารถเปลี่ยนชื่อ/a/bไป/a/cสร้างใหม่/a/bไดเรกทอรีและใหม่fileอยู่ในนั้น

เพื่อค้นหาเส้นทางที่$userจะสามารถแก้ไขได้ ในการระบุที่ 1 หรือ 2 เราไม่สามารถพึ่งพาการaccess(2)เรียกของระบบอีกต่อไป เราสามารถปรับfind -permวิธีการของเราในการสมมติการเข้าถึงไดเรกทอรีหรือเขียนการเข้าถึงไฟล์ทันทีที่คุณเป็นเจ้าของ:

groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
  \( \
    -user "$user" -o \
    \( -group $groups \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user "$user" -print -o \
    \( -group $groups \) \( ! -perm -g=w -o -print \) -o \
    ! -perm -o=w -o -print

เราสามารถระบุหมายเลข 3 และ 4 โดยการบันทึกอุปกรณ์และหมายเลขไอโหนดหรือไฟล์ทั้งหมดที่ผู้ใช้ $ มีสิทธิ์ในการเขียนและรายงานเส้นทางไฟล์ทั้งหมดที่มีหมายเลข dev + inode เหล่านั้น เวลานี้เราสามารถใช้แนวทางที่เชื่อถือได้มากขึ้น access(2):

สิ่งที่ต้องการ:

find / ! -type l -print0 |
  sudo -u "$user" perl -Mfiletest=access -0lne 'print 0+-w,$_' |
  perl -l -0ne '
    ($w,$p) = /(.)(.*)/;
    ($dev,$ino) = stat$p or next;
    $writable{"$dev,$ino"} = 1 if $w;
    push @{$p{"$dev,$ino"}}, $p;
    END {
      for $i (keys %writable) {
        for $p (@{$p{$i}}) {
          print $p;
        }
      }
    }'

5 และ 6 มีความซับซ้อนในขั้นแรกโดยtบิตของสิทธิ์ เมื่อนำไปใช้กับไดเรกทอรีต่างๆนั่นเป็นบิตการลบแบบ จำกัดซึ่งป้องกันผู้ใช้ (นอกเหนือจากเจ้าของไดเรกทอรี) จากการลบหรือเปลี่ยนชื่อไฟล์ที่พวกเขาไม่ได้เป็นเจ้าของ

ตัวอย่างเช่นถ้าเรากลับไปก่อนหน้านี้ตัวอย่างเช่นเราไปถ้าคุณมีสิทธิ์ในการเขียน/aแล้วคุณควรจะสามารถที่จะเปลี่ยนชื่อ/a/bไป/a/cแล้วสร้าง/a/bไดเรกทอรีและใหม่fileในการมี แต่ถ้าtบิตตั้งอยู่บน/aและคุณไม่ได้เป็นเจ้าของแล้วคุณจะสามารถทำมันได้หากคุณเป็นเจ้าของ/a /a/bที่ให้:

  • หากคุณเป็นเจ้าของไดเรกทอรีตาม 1 คุณสามารถให้สิทธิ์การเขียนกับตัวเองและ t บิตจะไม่นำไปใช้ (และคุณสามารถลบออกได้) ดังนั้นคุณสามารถลบ / เปลี่ยนชื่อ / สร้างไฟล์หรือ dir ใด ๆ ในนั้นได้ พา ธ ไฟล์ทั้งหมดที่อยู่ข้างใต้นั้นเป็นของคุณที่จะเขียนซ้ำกับเนื้อหาใด ๆ
  • หากคุณไม่ได้เป็นเจ้าของ แต่มีสิทธิ์เข้าถึงเพื่อเขียน:
    • ทั้งtบิตไม่มีการตั้งค่าและคุณอยู่ในกรณีเดียวกับข้างต้น (เส้นทางแฟ้มทั้งหมดเป็นของคุณ)
    • หรือตั้งค่าไว้แล้วคุณจะไม่สามารถแก้ไขไฟล์ที่คุณไม่ได้เป็นเจ้าของหรือไม่มีสิทธิ์เข้าถึงเพื่อเขียนดังนั้นสำหรับจุดประสงค์ของเราในการค้นหาพา ธ ไฟล์ที่คุณสามารถแก้ไขได้นั่นก็เหมือนกับว่าไม่มีสิทธิ์ในการเขียน

ดังนั้นเราจึงสามารถจัดการกับ 1, 2, 5 และ 6 ทั้งหมดด้วย:

find / -type d \
  \( \
    -user "$user" -prune -exec find {} + -o \
    \( -group $groups \) \( -perm -g=x -o -prune \) -o \
    -perm -o=x -o -prune \
  \) ! -type d -o -type l -o \
    -user "$user" \( -type d -o -print \) -o \
    \( -group $groups \) \( ! -perm -g=w -o \
       -type d ! -perm -1000 -exec find {} + -o -print \) -o \
    ! -perm -o=w -o \
    -type d ! -perm -1000 -exec find {} + -o \
    -print

นั่นและโซลูชันสำหรับ 3 และ 4 นั้นมีความเป็นอิสระคุณสามารถรวมเอาท์พุทของมันเพื่อรับรายการทั้งหมด:

{
  find / ! -type l -print0 |
    sudo -u "$user" perl -Mfiletest=access -0lne 'print 0+-w,$_' |
    perl -0lne '
      ($w,$p) = /(.)(.*)/;
      ($dev,$ino) = stat$p or next;
      $writable{"$dev,$ino"} = 1 if $w;
      push @{$p{"$dev,$ino"}}, $p;
      END {
        for $i (keys %writable) {
          for $p (@{$p{$i}}) {
            print $p;
          }
        }
      }'
  find / -type d \
    \( \
      -user "$user" -prune -exec sh -c 'exec find "$@" -print0' sh {} + -o \
      \( -group $groups \) \( -perm -g=x -o -prune \) -o \
      -perm -o=x -o -prune \
    \) ! -type d -o -type l -o \
      -user "$user" \( -type d -o -print0 \) -o \
      \( -group $groups \) \( ! -perm -g=w -o \
         -type d ! -perm -1000 -exec sh -c 'exec find "$@" -print0' sh {} + -o -print0 \) -o \
      ! -perm -o=w -o \
      -type d ! -perm -1000 -exec sh -c 'exec find "$@" -print0' sh {} + -o \
      -print0
} | perl -l -0ne 'print unless $seen{$_}++'

ควรมีความชัดเจนหากคุณอ่านทุกอย่างตอนนี้ส่วนหนึ่งเป็นอย่างน้อยเกี่ยวข้องกับสิทธิ์และความเป็นเจ้าของไม่ใช่คุณสมบัติอื่น ๆ ที่อาจอนุญาตหรือ จำกัด การเข้าถึงการเขียน (FS แบบอ่านอย่างเดียว ACLs ตั้งค่าสถานะไม่เปลี่ยนรูปได้คุณสมบัติด้านความปลอดภัยอื่น ๆ ... ) และในขณะที่เราดำเนินการในหลายขั้นตอนข้อมูลบางอย่างอาจไม่ถูกต้องหากไฟล์ / ไดเรกทอรีกำลังถูกสร้าง / ลบ / เปลี่ยนชื่อหรือแก้ไข / สิทธิ์ / ความเป็นเจ้าของของพวกเขาในขณะที่สคริปต์กำลังทำงานเช่นบนเซิร์ฟเวอร์ไฟล์ที่มีไฟล์หลายล้านไฟล์ .

หมายเหตุการพกพา

รหัสทั้งหมดนั้นเป็นมาตรฐาน (POSIX, Unix สำหรับtbit) ยกเว้น:

  • -print0เป็นส่วนขยายของ GNU ในขณะนี้ยังรองรับโดยการใช้งานอื่น ๆ ไม่กี่ ด้วยfindการใช้งานที่ขาดการสนับสนุนสำหรับมันคุณสามารถใช้-exec printf '%s\0' {} +แทนและแทนที่ด้วย-exec sh -c 'exec find "$@" -print0' sh {} +-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
  • perlไม่ใช่คำสั่งที่ระบุ POSIX แต่มีให้ใช้อย่างกว้างขวาง คุณต้องหรือสูงกว่าสำหรับperl-5.6.0-Mfiletest=access
  • zshไม่ใช่คำสั่งที่ระบุ POSIX ว่าzshรหัสดังกล่าวควรจะทำงานกับ zsh-3 (1995) และสูงกว่า
  • sudoไม่ใช่คำสั่งที่ระบุ POSIX รหัสควรทำงานกับเวอร์ชันใดก็ได้ตราบใดที่การกำหนดค่าระบบอนุญาตให้ทำงานperlในฐานะผู้ใช้ที่กำหนด

การเข้าถึงการค้นหาคืออะไร? ฉันไม่เคยได้ยินเรื่องนี้ในการอนุญาตแบบดั้งเดิม: อ่านเขียนดำเนินการ
bela83

2
@ bela83, ดำเนินการอนุญาตบนไดเรกทอรี (คุณไม่ดำเนินการไดเรกทอรี) แปลว่าจะค้นหา นั่นคือความสามารถในการเข้าถึงไฟล์ในนั้น คุณสามารถแสดงรายการเนื้อหาของไดเรกทอรีหากคุณได้รับอนุญาตให้อ่าน แต่คุณไม่สามารถทำอะไรกับไฟล์ที่อยู่ในนั้นได้เว้นแต่คุณจะได้xรับอนุญาตให้ค้นหา ( บิต) ในไดเรกทอรี คุณสามารถมีสิทธิ์ในการค้นหา แต่ไม่อ่านหมายถึงไฟล์ที่ซ่อนอยู่ในตัวคุณ แต่ถ้าคุณรู้ชื่อพวกเขาคุณสามารถเข้าถึง ตัวอย่างทั่วไปคือไดเรกทอรีไฟล์เซสชันของ php (บางอย่างเช่น / var / lib / php)
Stéphane Chazelas

2

คุณสามารถรวมตัวเลือกกับfindคำสั่งดังนั้นมันจะค้นหาไฟล์ที่มีโหมดและเจ้าของที่ระบุ ตัวอย่างเช่น

$ find / \( -group staff -o -group users \) -and -perm -g+w

คำสั่งดังกล่าวจะแสดงรายการทั้งหมดที่อยู่ในกลุ่ม "พนักงาน" หรือ "ผู้ใช้" และมีสิทธิ์ในการเขียนสำหรับกลุ่มนั้น

คุณควรตรวจสอบรายการที่ผู้ใช้ของคุณเป็นเจ้าของและไฟล์ที่โลกเขียนได้ดังนั้น:

$ find / \( -user yourusername -or \
             \(  \( -group staff -o -group users \) -and -perm -g+w \
             \) -or \
            -perm -o+w \
         \)

อย่างไรก็ตามคำสั่งนี้จะไม่ตรงกับรายการที่มี ACL ที่ขยายเพิ่ม ดังนั้นคุณอาจsuค้นหารายการที่เขียนได้ทั้งหมด:

# su - yourusername
$ find / -writable

ที่จะบอกว่าไฟล์ที่มีr-xrwxrwx yourusername:anygroupหรือr-xr-xrwx anyone:staffเขียนได้
Stéphane Chazelas

นอกจากนี้ยังจะรายงานว่าไฟล์ที่เขียนได้ซึ่งอยู่ในไดเรกทอรีyourusernameไม่มีสิทธิ์เข้าถึง
Stéphane Chazelas

1

วิธีการขึ้นอยู่กับสิ่งที่คุณกำลังทดสอบจริง ๆ

  1. คุณต้องการให้แน่ใจว่าการเข้าถึงการเขียนเป็นไปได้หรือไม่?
  2. คุณต้องการให้แน่ใจว่าไม่มีการเข้าถึงเพื่อเขียนหรือไม่?

นี่เป็นเพราะมีหลายวิธีที่จะมาถึงข้อ 2) และคำตอบของStéphaneครอบคลุมบ่อน้ำเหล่านี้ (ไม่เปลี่ยนรูปเป็นสิ่งที่ต้องจำ) และจำได้ว่ามีวิธีการทางกายภาพเช่นกันเช่นยกเลิกการต่อเชื่อมไดรฟ์หรือทำให้อ่านได้อย่างเดียว ระดับฮาร์ดแวร์ (แท็บฟลอปปี้) ฉันเดาว่าไฟล์หลายพันไฟล์ของคุณอยู่ในไดเรกทอรีที่แตกต่างกันและคุณต้องการรายงานหรือคุณกำลังตรวจสอบกับรายการหลัก (การใช้หุ่นกระบอกในทางที่ผิดอีกเรื่องกำลังรอให้เกิดขึ้น)

คุณน่าจะต้องการให้ Tree-Traversal ของStéphaneและ "เข้าร่วม" เอาท์พุทพร้อมกับรายการถ้าจำเป็น (su ก็จะหายตัวไปกับการดำเนินการในไดเรกทอรีหลัก?) หากการตั้งครรภ์แทนเป็นปัญหาด้านประสิทธิภาพคุณกำลังทำสิ่งนี้กับผู้ใช้ "จำนวนมาก" หรือไม่? หรือมันเป็นแบบสอบถามออนไลน์ หากนี่เป็นข้อกำหนดถาวรอย่างต่อเนื่องอาจถึงเวลาพิจารณาผลิตภัณฑ์ของบุคคลที่สาม


0

คุณทำได้...

find / ! -type d -exec tee -a {} + </dev/null

... สำหรับรายการของไฟล์ทั้งหมดที่ผู้ใช้ไม่สามารถเขียนตามที่เขียนไปยัง stderr ในแบบฟอร์ม ...

"tee: cannot access %s\n", <pathname>" 

... หรือคล้ายกัน

ดูความคิดเห็นด้านล่างเพื่อดูหมายเหตุเกี่ยวกับปัญหาที่อาจเกิดขึ้นกับวิธีการนี้และคำอธิบายด้านล่างว่าทำไมจึงอาจใช้งานได้ แม้ว่าจะดูดีมากขึ้นคุณควรใช้ findไฟล์ปกติเช่น:

find / -type f -exec tee -a {} + </dev/null

กล่าวโดยย่อteeจะพิมพ์ข้อผิดพลาดเมื่อพยายามopen()ไฟล์ที่มีทั้งสองแฟล็ก ...

O_WRONLY

เปิดสำหรับการเขียนเท่านั้น

O_RDWR

เปิดให้อ่านและเขียน ผลลัพธ์ไม่ได้ถูกกำหนดหากใช้แฟล็กนี้กับ FIFO

... และพบ ...

[EACCES]

สิทธิ์การค้นหาถูกปฏิเสธในส่วนประกอบของคำนำหน้าพา ธ หรือไฟล์มีอยู่และสิทธิ์ที่ระบุโดย oflag ถูกปฏิเสธหรือไฟล์ไม่มีอยู่และสิทธิ์การเขียนถูกปฏิเสธสำหรับไดเรกทอรีหลักของไฟล์ที่จะสร้างหรือ O_TRUNC คือ สิทธิ์ที่ระบุและการเขียนถูกปฏิเสธ

... ตามที่ระบุไว้ที่นี่ :

teeยูทิลิตี้จะคัดลอกเข้ามาตรฐานการส่งออกมาตรฐานการทำสำเนาในศูนย์หรือมากกว่าไฟล์ ยูทิลิตี tee จะต้องไม่บัฟเฟอร์เอาต์พุต

หาก-aไม่ได้ระบุตัวเลือกไว้ไฟล์เอาต์พุตจะต้องเขียน (ดูที่ไฟล์อ่านเขียนและสร้าง ) ...

... POSIX.1-2008 ต้องการฟังก์ชันการทำงานเทียบเท่ากับการใช้O_APPEND ...

เพราะมันต้องตรวจสอบแบบเดียวกับที่test -wทำ ...

-w ชื่อพา ธ

จริงถ้าชื่อพา ธแก้ไขไปยังรายการไดเรกทอรีที่มีอยู่สำหรับไฟล์ที่ได้รับอนุญาตให้เขียนไปยังแฟ้มจะได้รับตามที่กำหนดไว้ในไฟล์อ่านเขียนและการสร้าง เท็จหากชื่อพา ธไม่สามารถแก้ไขได้หรือหากชื่อพา ธแก้ไขไปยังรายการไดเรกทอรีที่มีอยู่สำหรับไฟล์ที่ไม่อนุญาตให้เขียนไฟล์

พวกเขาทั้งสองตรวจสอบeAccess


คุณอาจพบว่ามีจำนวนไฟล์ที่เปิดพร้อมกันด้วยวิธีการนั้น จำกัด (เว้นแต่ว่าไฟล์มีจำนวนน้อย) ระวังผลข้างเคียงกับอุปกรณ์และท่อที่มีชื่อ คุณจะได้รับข้อความแสดงข้อผิดพลาดที่แตกต่างกันสำหรับซ็อกเก็ต
Stéphane Chazelas

@ StéphaneChazelas - อืมทั้งหมด - ฉันคิดว่ามันอาจจะเป็นจริงที่teeจะแขวนเว้นแต่จะถูกขัดจังหวะอย่างชัดเจนหนึ่งครั้งต่อการทำงาน มันเป็นสิ่งที่ใกล้เคียงที่สุดที่ฉันสามารถนึกได้ถึง[ -w... แม้ว่า - เอฟเฟกต์ควรจะอยู่ใกล้กับสิ่งที่รับประกันว่าผู้ใช้จะสามารถเพิ่มไฟล์ได้ ง่ายกว่าตัวเลือกอย่างใดอย่างหนึ่งจะpaxมี-oตัวเลือกรูปแบบและ / หรือ-tสำหรับการตรวจสอบกับEACCESS- แต่ทุกครั้งที่ฉันแนะนำให้paxคนดูเหมือนจะยักออก และต่อไปสิ่งเดียวที่paxฉันพบที่ตรงกับ std มีของ AST - ในกรณีที่คุณอาจใช้พวกเขาlsเช่นกัน
mikeserv
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.