문자열 작업 없이 *파일 시스템의 파티션 및 블록 장치 찾기

문자열 작업 없이 *파일 시스템의 파티션 및 블록 장치 찾기

/dev/sda5또는 와 같은 파일 시스템이 있는 경우 /dev/mmcblk0p5문자열 조작 없이 파티션 번호( 5) 및 블록 장치(예: )를 가져오는 것이 가능합니까 /dev/mmcblk0, 아니면 파티션 번호( ) 및 블록 장치(예:)를 가져오는 데 필요한 문자열 구문 분석 양을 최소화하여 얻을 수 있습니까?

커널이 5.x라고 가정합니다. 아래 예는 5.10을 실행하는 장치에서 가져온 것입니다. 그러나 대답이 커널 또는 구성과 관련된 경우 대답에 이를 표시하십시오.

세부정보/예:

udevadm info(v247에서) 속성을 포함하여 많은 중요한 정보를 반환합니다 PARTN. 하지만나는 "속성 X의 값을 인쇄"하는 방법이 있다고 믿지 않습니다. v247(아마도 v251?)에서는 속성과 값을 찾기 위해 출력을 구문 분석해야 합니다. 예를 들면 다음과 같습니다.

udevadm info /dev/disk/by-label/rootfs | grep -e '^E: PARTN=' | awk -F '=' '{print $2}'    # prints '2'

udevadmmajor나중에 도움이 될 수 있는 숫자 도 포함되어 있지만 "디스크" 속성이나 이와 유사한 것은 없습니다.

남은 것을 /sys/class/block/mmcblk0p2/partition제거할 의향이 있다고 가정하고 sysfs 파일을 읽어 파티션 번호를 찾을 수도 있습니다 ./dev/mmcblk0p2

$ cat /sys/class/block/mmcblk0p2/partition 
2

major:minor같은 방식으로 숫자도 얻을 수 있는 것 같습니다 (최소한의 문자열 토큰을 사용하여).

$ cat /sys/class/block/mmcblk0p2/dev 
179:2

/sys/class/block/mmcblk0p2불행하게도 아래의 어떤 것도 파티션이 있는 블록 장치를 직접 가리키는 것 같지 않습니다 . mmcblk0이 경우입니다.

이 디스크를 얻으려면 아래의 모든 경로를 검색하여 /sys/block/파티션이 있는 경로를 찾을 수 있습니다. 즉, /sys/block/mmcblk0/mmcblk0p2이 경로가 존재합니까? 그렇다면 세 번째 경로 구성 요소, 즉 mmcblk0디스크가 됩니다.

major또는 다음과 같이 파티션( 179이 경우) 의 숫자를 사용할 수 있습니다 .

$ realpath /dev/block/179\:0
/dev/mmcblk0

구문 분석도 가능합니다 /proc/partitions(다시 문자열 구문 분석!).

$ cat /proc/partitions
major minor  #blocks  name

..snip..
 179        0    7782400 mmcblk0
 179        1      96632 mmcblk0p1
 179        2    3145728 mmcblk0p2

일부 문자열 스푸핑이 필요하다고 가정할 때 "가장 쉬운"/가장 취약한 방법은 무엇입니까?

배경

여러 분할 구성표를 지원하는 일반 ARM 장치 이미지가 있습니다. 일부 ARM 장치에는 특정 파티션 구성표가 필요한 반면 다른 장치는 하나의 파티션만 사용할 수 있습니다. 디스크를 채우기 위해 rootfs를 확장하는 스크립트가 있습니다.

파티션 크기를 조정하려면 다음을 실행합니다.

sfdisk --no-reread "$DISK" -N "$PART" <<EOF
, $SIZE, L
EOF

그 중에는 예를 들어 DISK=/dev/mmcblk0PART=2. 그런 다음 우리는 그것을 사용합니다 resize2fs.

답변1

/sys/block/ 아래의 모든 경로를 검색하여 파티션이 있는 경로를 찾을 수 있습니다.

모든 경로를 검색하는 대신 심볼릭 링크만 읽을 수 있습니다.

$ readlink /sys/class/block/sdb17
[…]/block/sdb/sdb17
$ basename "$(realpath /sys/class/block/sdb17/..)"
sdb
$ basename "$(realpath /sys/class/block/nvme0n1p2/..)"
nvme0n1

또는 다음과 같이 파티션의 주요 번호(이 경우 179)를 사용할 수 있습니다.

파티션 번호가 크면 실패합니다.

$ cat /sys/block/sdb/sdb17/dev
259:1
$ realpath /dev/block/259:0
/dev/sdb16

답변2

udev 규칙을 생성하는 경우 매개변수를 사용하여 규칙에서 스크립트로 환경 변수를 전달할 수 있습니다.

%n장치의 커널 번호는 어디에 있습니까( 당신에게 주어진 %n것 입니다 )./dev/sda11

%P상위 장치의 노드 이름은 어디에 있습니까(예: 귀하에게 %P제공됨 ). 따라서 스크립트에 like를 추가하여 작업을 수행할 수 있습니다 ./dev/sda1sda%P/dev/dev/%P

따라서 이 작업을 수행하는 간단한 예는 먼저 udev 규칙을 만드는 것입니다(아래 표시된 것보다 장치를 더 잘 식별해야 합니다).

KERNEL=="sd[a-z][0-9]", ACTION=="add", RUN+="/path/to/script.sh %P %n"

그런 다음 그에 따라 스크립트를 편집하십시오.

sfdisk --no-reread "/dev/$1" -N "$2" <<EOF
, $SIZE, L
EOF

$1어디에 있을 것인가 %P, $2어디에 있을 것인가%n

이는 장치가 연결될 때마다 스크립트가 실행되기를 원한다고 가정하지만(이로 인해 ACTION=="add"). 이는 실행하는 데 시간이 오래 걸리지 않는 스크립트에만 작동합니다(udev는 장기 실행 프로세스를 처리하지 않습니다).

이 문제를 해결하려면 환경 변수를 systemd 인스턴스 유닛에 전달한 다음 스크립트를 호출하면 됩니다.

관련 정보