//go:build linux package repository import ( "os" "golang.org/x/sys/unix" ) // linuxImmutableFlag ist das Unveraenderlich-Kennzeichen des Dateisystems. // // Der Wert steht als FS_IMMUTABLE_FL in ; x/sys fuehrt ihn nicht, // weshalb er hier benannt wird statt als nackte Zahl im Code zu stehen. const linuxImmutableFlag = 0x00000010 // immutableFlagSupported meldet, ob dieses System ein Unveraenderlich-Kennzeichen kennt. // // Linux kennt es auf ext2/3/4, xfs und btrfs. Ob es sich setzen laesst, haengt // zusaetzlich an der Berechtigung CAP_LINUX_IMMUTABLE — deshalb ist die // Unterstuetzung hier nur die halbe Auskunft. Die andere Haelfte liefert die // Messung in MeasureEnforcement, die es tatsaechlich versucht. func immutableFlagSupported() bool { return true } // setImmutableFlag setzt oder entfernt das Unveraenderlich-Kennzeichen. func setImmutableFlag(filePath string, shouldBeImmutable bool) error { // O_RDONLY genuegt: Die Kennzeichen haengen am Inode, nicht am Inhalt. Eine // bereits unveraenderliche Datei liesse sich zum Schreiben gar nicht oeffnen // — das Entfernen des Kennzeichens waere damit unmoeglich. fileHandle, openError := os.OpenFile(filePath, os.O_RDONLY, 0) if openError != nil { return openError } defer func() { _ = fileHandle.Close() }() currentFlags, readError := unix.IoctlGetInt(int(fileHandle.Fd()), unix.FS_IOC_GETFLAGS) if readError != nil { return &os.PathError{Op: "ioctl(FS_IOC_GETFLAGS)", Path: filePath, Err: readError} } updatedFlags := currentFlags &^ linuxImmutableFlag if shouldBeImmutable { updatedFlags = currentFlags | linuxImmutableFlag } if updatedFlags == currentFlags { return nil } if writeError := unix.IoctlSetPointerInt(int(fileHandle.Fd()), unix.FS_IOC_SETFLAGS, updatedFlags); writeError != nil { return &os.PathError{Op: "ioctl(FS_IOC_SETFLAGS)", Path: filePath, Err: writeError} } return nil }